C++ AMPを用いたGPUプログラミングwiki
首都大学東京 田川研究室
C++ AMP 目次へ

GPUを探してみよう!

必要な機能を集めていく方針で説明していきます。

とりあえず、PCに刺さっているGPUを調べないと始まりません。どのGPUに演算させるべきかも決められないでしょう。
よって利用可能な全アクセラレータを検索します。これらの処理にはacceleratorオブジェクトを用います。
    vector<accelerator> vAcs;//accelerator型変数の配列を管理するオブジェクト

    //利用可能なアクセラレータの情報が入ったacceleratorオブジェクトの配列を返す関数
    vAcs = accelerator::get_all();

    //得られたacceleratorオブジェクトの数だけ、ループをまわす。
    for (int i = 0; i < vAcs.size(); i++) {

    //GPUの名前を取得する関数、get_description()を呼び出す
        wcout << vAcs[i].get_description() << "\n";
    }
これですべてのアクセラレータ(以降GPU)を画面に表示できると思います。しかしこれだけでは変なGPUも表示されていると思います。刺さっているのは1枚なのに、4つ表示されていたり・・・
これはエミュレータで構成されているGPUで、実際に用いることはありません。デバッグには使えるのでしょうか?
よってこれらを排除したものを表示します。
    vector<accelerator> vAcs;//accelerator型変数の配列を管理するオブジェクト

    vector<accelerator> vNoEmurate;

    vAcs = accelerator::get_all();
    for (int i = 0; i < vAcs.size(); i++) {

        //エミュレータ以外を集める
        if(vAcs[i].is_emulated == false)
        {
            //エミュレータのGPUを集めた配列を作る。

            vNoEmurate.push_back(vAcs[i]);
            //push_backは配列の要素を追加できる関数
        }
    }
これでエミュレータ動作のGPUを除外できます。vectorクラスを用いているのでこのように簡単に調べられます。vAcsにはエミュレータ動作以外のGPUを示すacceleratorオブジェクトが入っていることでしょう。

では、以下にエミュレータ動作のGPUを除外し、搭載メモリ量、倍精度のサポート、ディスプレイ出力に使われているかどうか等の情報を表示し、使うGPUを選べるコードを示します。
#include <amp.h>
#include <iostream>
#include <vector>
using  concurrency::accelerator;
using  std::cout;
using  std::cin;
using  std::wcout;
using  std::vector


accelerator ChoseAccelerator()//アクセラレータを選びます。例外が投げられるので注意する。
{
    //全アクセラレータを取得。
    vector<accelerator> allAccl = accelerator::get_all();

    
    vector<accelerator> validAccl;
    //明らかに不適切なものを除外しておく。CPU,Direct3Dなど。
    int numAcs = allAccl.size();//配列のサイズを取得。

    for(int i=0;i<numAcs;i++)
    {
        if(!allAccl[i].is_emulated)
        {
            validAccl.push_back(allAccl[i]);//選ばれし者へ追加。
        }
    }

    if(validAccl.size() == 0)
    {
        cout << "GPGPUに利用できそうなGPUはなさそうじゃの。";
        throw -1;//例外を投げる。
    }

    //選ばれし者たちから、ユーザーに選んでもらう。
    wcout << "以下の候補から選びんす。" << "\n\n";
    for(int i=0;i<validAccl.size();i++)
    {
        wcout << i <<" : "<< validAccl[i].get_description() << "\n";
        cout << "   メモリ量                             : "
            << (double)validAccl[i].dedicated_memory/1024/1000 << " [GB]\n";
        cout << "   完全なる倍精度浮動小数演算のサポート : ";
        if(validAccl[i].supports_double_precision)
            cout << "true\n";
        else
            cout << "false\n";

        cout << "   ディスプレイ出力に使われているか     : ";
        if(validAccl[i].has_display)
            cout << "true\n";
        else
            cout << "false\n";
    }
    printf("\nさあ、好きなものを選んでくりゃれ。自己責任で。\n\n");

    cin.exceptions(ios::failbit);

    int selAcs;
    while(true)
    {
        cout << "デバイス番号 = ";
        try{
            cin >> selAcs ;
        }
        catch(...){
            cout << "この甲斐性なしめ。数字を入力せんか。\n";
            cin.clear();
            cin.seekg(0);
            continue;
        }
        cout << "\n";

        if(0 <= selAcs && selAcs < validAccl.size())
        {
            cout << selAcs <<"番じゃな。了解じゃ。\n";
            return validAccl[selAcs];
        }

        cout << "たわけ。0~" << validAccl.size() -1 << "までじゃ。"
             <<selAcs<<"番のGPUなんて存在せん。\n";
    }


    throw -1;//例外を投げる。ここに到達することはないはずだが・・・。
}
これで、使用するGPUを示すacceleratorオブジェクトを手に入れることができました。
次からはこのオブジェクトを用いていろんな操作をしていきます。