2016-08-12 15 views
0

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

答えて

0

問題が発生していることがわかりました。打ち上げが非同期的に行われている間、私は打ち上げの流れを含めなかった。

ように私の打ち上げを変更する:

gpu.Launch(グリッド寸法、ブロックサイズ、streamIDで).simulation(DF);

が解決しました。開始はストリーム0で行われ、ストリーム1と2は同期されていたようです。時にはデータが設定されることもありますが、データが設定されないこともあります。競合状態。

関連する問題