GPUコード内(ラムダ式)からは、parallel_for_eachが呼び出された関数ないのローカル変数を参照することができます。
これにより細かいパラメータ等を送ることが容易になります。1つ2つの変数くらいならわざわざarrayクラスを用いなくても良いということです。
グローバル変数、クラスのメンバ等は参照できません。参照したい場合は一度ローカル変数に代入してからにします。規格なのでしょうがないです。
accelerator Acs;
array<int , 2> *pvA;
pvA = new array<int , 2>(100 , 100, Acs.get_default_view());
array_view<int , 2> vaC = *pvA;
extent<2> exA;
exA[0] = 100;
exA[1] = 100;
int aa=2;
parallel_for_each(
Acs.get_default_view() ,
exA ,
[=](index<2> iC) restrict(amp)
{
int i = iC[0];
int j = iC[1];
int ab;
int ac;
vaC[iC] = aa;
}
);
ご覧のようにCPU側のメモリに配置されるであろうaaなる変数を、GPU上で実行されるコードでそのまま利用できています。これくらいのこまごました変数ならば、parallel_for_eachを呼び出し、GPUへ処理を渡す時に一緒に転送してくれます。
なのでユーザーはパラメータなどのデータ変数に関する転送を気に掛ける必要がありません。
しかし、この便利な機能にはいくつもの制限があります。以下に列挙します。
GPUへ渡せる変数の制限
- 値渡しで転送される
- ローカル変数のみ
- ポインタは不可
- 関数は渡せない
等ですかね。特にローカル変数しか渡せず、ポインタは渡せないという点が大きな障害となります。
まず、グローバル変数などをGPUへ渡したい場合、一度each_for_parallelが呼び出される関数内のローカル変数へ代入してからになります。
そしてポインタを渡す場合、例えば配列で渡したい場合などですね。これはあきらめるしかありません。あまりにも大きい配列であるならばそもそもarrayオブジェクトでデータを参照すべきです。3つ程度の配列であるならば、以下の記述をお勧めします。
accelerator Acs;
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;
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++;
}
}
);
上記記述は便利なんじゃないでしょうかね?
私はこれを思いつくまで大変苦労しました。