CUDAfy .NETを使用してGPGPUに非同期カーネルコールを作成しようとしています。OpenCLを使用してCUDAfy .NETでカーネルを非同期で実行する
カーネルに値を渡してそれらをホストにコピーすると、私はいつも期待した値を得ることができません。
私はバイトバーを持つ構造体はFooあります
[Cudafy]
public struct Foo {
public byte Bar;
}
をそして私は、私が電話をかけたいカーネルがあります。
[Cudafy]
public static void simulation(GThread thread, Foo[] f)
{
f[0].Bar = 3;
thread.SyncThreads();
}
を私が試したstreamIDで= 1(とシングルスレッドを持っています複数のスレッドを使用して、問題に気づいた.1つのスレッドを減らしても問題は解決していないようだ。
//allocate
streamID = 1;
count = 1;
gpu.CreateStream(streamID);
Foo[] sF = new Foo[count];
IntPtr hF = gpu.HostAllocate<Foo>(count);
Foo[] dF = gpu.Allocate<Foo>(sF);
while (true)
{
//set value
sF[0].Bar = 1;
byte begin = sF[0].Bar;
//host -> pinned
GPGPU.CopyOnHost<Foo>(sF, 0, hF, 0, count);
sF[0].Bar = 2;
lock (gpu)
{
//pinned -> device
gpu.CopyToDeviceAsync<Foo>(hF, 0, dF, 0, count, streamID);
//run
gpu.Launch().simulation(dF);
//device -> pinned
gpu.CopyFromDeviceAsync<Foo>(dF, 0, hF, 0, count, streamID);
}
//WAIT
gpu.SynchronizeStream(streamID);
//pinned -> host
GPGPU.CopyOnHost<Foo>(hF, 0, sF, 0, count);
byte end = sF[0].Bar;
}
//de-allocate
gpu.Free(dF);
gpu.HostFree(hF);
gpu.DestroyStream(streamID);
まず、GPUでストリームを作成します。
私は、サイズ1(sF)の標準構造Foo配列を作成し、そのBar値を1に設定します。次に、Fooのホスト(hF)に固定メモリーを作成します。私はまた、Foo(dF)用のメモリを作成します。
構造体のBar値を1に初期化してから、固定されたメモリにコピーします(チェックとして、構造体の値を固定した後に構造体を2に設定すると、後でその理由がわかります)。次に、私はGPUへの完全なアクセスを確保するためにロックを使用し、dFへのコピー、カーネルに対する実行、およびdFからのコピーをキューに入れます。この時点で、いつGPUで実際に実行されるのかわからないので、デバイスが完了するまでSynchronizeStreamを呼び出してホストを待機させることができます。
終了したら、固定メモリー(hF)を共有メモリー(sF)にコピーできます。値を取得すると、通常は3(デバイスに設定されています)または1(カーネルに値が設定されていないか、新しい値が固定メモリにコピーされていないことを意味します)です。構造体に2の値が決してないので、固定されたメモリが構造体にコピーされていることはわかります。
実行回数が多いと、start = 1およびend = 3以外の結果が実行されます。それは常にbegin = 1、end = 1であり、それは時間の約5-10%で起こります。
なぜこのようなことが起こるのかわかりません。私はそれが一般的に競合状態を強調していることを知っていますが、同期呼び出しを呼び出すことによって、非同期呼び出しが予測可能な方法で動作することが期待されます。
このコードでこのような問題が発生するのはなぜですか?
ありがとうございました!
-phil