0

いくつかのタスクを CUDA GPU に「マップ」しようとしています。処理するタスクが n 個あります。(疑似コードを参照)

malloc an boolean array flag[n] and initialize it as false.
for each work-group in parallel do
    while there are still unfinished tasks do
        Do something;
        for a few j_1, j_2, .. j_m (j_i<k) do
            Wait until task j_i is finished; [ while(flag[j_i]) ;  ]
            Do Something;
        end for
        Do something;
        Mark task k finished;  [  flag[k] = true;  ]
    end while
end for

何らかの理由で、別のスレッド ブロックでスレッドを使用する必要があります。

問題は、タスク j_i が完了するまで待機を実装する方法です。タスク k の終了をマークします。CUDAで。私の実装では、ブール配列をフラグとして使用します。次に、タスクが完了したらフラグを設定し、フラグを読み取ってタスクが完了したかどうかを確認します。

しかし、それは小さなケース、1 つの大きなケースでのみ機能し、GPU は不明な理由でクラッシュします。CUDA で待機マークを実装するより良い方法はありますか。

これは基本的に、CUDA でのスレッド間通信の問題です。

4

4 に答える 4

2

スレッドブロック内での同期は、を使用して簡単に行え__syncthreads()ます。ただし、スレッドブロック間の同期はより注意が必要です。プログラミングモデルの方法は、2つのカーネルに分割することです。

あなたがそれについて考えるならば、それは理にかなっています。実行モデル(CUDAとOpenCLの両方)は、処理ユニットで実行される一連のブロック用ですが、いつについては何も述べていません。これは、一部のブロックは実行されますが、他のブロックは実行されないことを意味します(待機します)。したがって、__syncblocks()thenがある場合、すでに実行されているものは停止しますが、実行されていないものはバリアに到達しないため、デッドロックのリスクがあります。

ブロック間で情報を共有することはできますが(たとえば、グローバルメモリとアトミックを使用して)、グローバル同期はできません。

あなたがやろうとしていることに応じて、問題を解決または分解する別の方法がしばしばあります。

于 2012-09-12T20:54:07.647 に答える
1

スレッドブロックは任意の順序でスケジュールでき、それらの間で同期または通信する簡単な方法がないため、要求していることは簡単には実行できません。CUDAプログラミングガイドから:

並列ワークロードの場合、データを相互に共有するために一部のスレッドを同期する必要があるために並列処理が中断されるアルゴリズムのポイントでは、2つのケースがあります。これらのスレッドが同じブロックに属している場合は、__syncthreadsを使用する必要があります。 ()そして、同じカーネル呼び出し内の共有メモリを介してデータを共有するか、異なるブロックに属します。この場合、2つの別々のカーネル呼び出しを使用してグローバルメモリを介してデータを共有する必要があります。1つはグローバルメモリへの書き込み用、もう1つはグローバルメモリからの読み取り用です。2番目のケースは、余分なカーネル呼び出しとグローバルメモリトラフィックのオーバーヘッドを追加するため、最適ではありません。

したがって、必要なすべての通信をスレッドブロック内に収めることができない場合は、必要なことを実行するために複数のカーネル呼び出しを行う必要があります。

OpenCLとの違いはないと思いますが、OpenCLでも仕事をしていません。

于 2012-09-12T20:58:10.827 に答える
1

この種の問題は、少し異なるアプローチで解決するのが最適です。

スレッドに固定タスクを割り当てないでください。タスクが使用可能になるまでスレッドを強制的に待機させます (スレッドはブロックできないため、CUDA では不可能です)。

代わりに、(アトミック操作を使用して) 使用可能なタスクのリストを保持し、各スレッドにそのリストからタスクを取得させます。

これを実装してコーナー ケースを正しく設定するのはまだ難しいですが、少なくとも可能です。

于 2012-09-12T22:59:25.590 に答える
0

CUDAで実装する必要はないと思います。すべてのものはCPU上で実装できます。タスクが完了するのを待ってから、別のタスクをランダムに実行します。CUDA で実装する場合は、すべてのフラグが true になるまで待つ必要はありません。最初は、すべてのフラグが false であることを知っています。したがってDo something、すべてのスレッドに対して並行して実装し、フラグを true に変更します。

CUDAで実装したい場合は、実行前と実行後のフラグの変化がわかるようint flagに、終了後に1を追加し続けます。Do somethingDo something

質問が間違っていた場合は、コメントしてください。私は答えを改善しようとします。

于 2012-09-14T18:43:50.083 に答える