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

GPUへの細かい値の転送

GPUコード内(ラムダ式)からは、parallel_for_eachが呼び出された関数ないのローカル変数を参照することができます。 これにより細かいパラメータ等を送ることが容易になります。1つ2つの変数くらいならわざわざarrayクラスを用いなくても良いということです。
グローバル変数、クラスのメンバ等は参照できません。参照したい場合は一度ローカル変数に代入してからにします。規格なのでしょうがないです。
    accelerator Acs;//選ばれたacceleratorオブジェクトが入っているとします。

    array<int , 2> *pvA;

    pvA = new array<int , 2>(100 , 100, Acs.get_default_view());
    array_view<int , 2> vaC = *pvA;

    extent<2> exA;

    //100*100スレッド発行予定。
    exA[0] = 100; 
    exA[1] = 100; 

    int aa=2;
    parallel_for_each(
        Acs.get_default_view() ,//計算させたいGPUを指定。
        exA  ,                  //スレッド数を指定。
        [=](index<2> iC) restrict(amp)   
        {
            //このコードは並列に動く。
            //ここに宣言された変数は各スレッドで個別に確保されます。
            //スレッド間データ交換にはつかえません。

            int i = iC[0]; //iC[0]にはこの場合0-99のスレッド番号が入っている。
            int j = iC[1]; //iC[1]にはこの場合0-99のスレッド番号が入っている。

            int ab;
            int ac;


            vaC[iC]   = aa;   //aaの値をGPU上で参照できます。
        }
    );

ご覧のようにCPU側のメモリに配置されるであろうaaなる変数を、GPU上で実行されるコードでそのまま利用できています。これくらいのこまごました変数ならば、parallel_for_eachを呼び出し、GPUへ処理を渡す時に一緒に転送してくれます。
なのでユーザーはパラメータなどのデータ変数に関する転送を気に掛ける必要がありません。

しかし、この便利な機能にはいくつもの制限があります。以下に列挙します。

GPUへ渡せる変数の制限
等ですかね。特にローカル変数しか渡せず、ポインタは渡せないという点が大きな障害となります。
まず、グローバル変数などをGPUへ渡したい場合、一度each_for_parallelが呼び出される関数内のローカル変数へ代入してからになります。
そしてポインタを渡す場合、例えば配列で渡したい場合などですね。これはあきらめるしかありません。あまりにも大きい配列であるならばそもそもarrayオブジェクトでデータを参照すべきです。3つ程度の配列であるならば、以下の記述をお勧めします。
    accelerator Acs;//選ばれたacceleratorオブジェクトが入っているとします。

    float a1,a2,a3;
    float vA[3] = {2,2,1};
    
    extent<1> exA;

    exA[0] = 100; 
    a1 = vA[0];
    a2 = vA[1];
    a3 = vA[2];

    parallel_for_each(                                                 
        Acs.get_default_view() ,                                       
        exA ,                                                          
        [=](index<2> indC) restrict(amp)
        {                                                  
            float x;                                           
            float vAa[3] = {a1,a2,a3};                         
                                                                
            x = vAa[0]*vAa[1]*vAa[2];                           
        }
    );

GPUのコード内で配列を組立直すのですが・・・ほかに良い記述が思いつきませんでした。
なお、配列の再構築において、以下のようなコードも組めます。
    accelerator Acs;//選ばれたacceleratorオブジェクトが入っているとします。

    array<float , 1> vAGpu(100 , Acs.get_default_view() );
    array<float , 1> vBGpu(100 , Acs.get_default_view() );
    array<float , 1> vCGpu(100 , Acs.get_default_view() );
        
    array_view<float , 1> vAGpuView = vAGpu;
    array_view<float , 1> vBGpuView = vBGpu;
    array_view<float , 1> vCGpuView = vCGpu;

    extent<1> exA;

    exA[0] = 100; 

    parallel_for_each(                                                 
        Acs.get_default_view() ,                                       
        exA ,                                                          
        [=](index<2> indC) restrict(amp)       
        {                                                                                     
            array_view<float , 1> vAView[3] = {vAGpuView , vBGpuView , vCGpuView};                                      
            inr c;                                                         
            while(c<3)                                                 
            {                                                           
                vAView[c][indC] = c;      
                c++;                                                
            }                                               
                                                      
        }
    );

上記記述は便利なんじゃないでしょうかね?
私はこれを思いつくまで大変苦労しました。