1

CUDA を使用して GPU に次の種類のパイプラインを実装しようとしています。

パイプライン

Host2Device コピー、カーネル呼び出し、Device2Host コピーのそれぞれに 4 つのストリームがあります。ただし、カーネル呼び出しは、次のストリームの Host2Device コピーが完了するまで待機する必要があります。

cudaStreamWaitEvent同期に使用するつもりでした。ただし、ドキュメントによると、これcudaEventRecordは、対応するイベントに対して以前に呼び出された場合にのみ機能します。そして、これはこのシナリオには当てはまりません。

ストリームは、基本的に次のように見える個別の CPU スレッドによって管理されます。

Do some work ...
cudaMemcpyAsync H2D
cudaEventRecord (event_copy_complete[current_stream])
cudaStreamWaitEvent (event_copy_complete[next_stream])
call kernel on current stream
cudaMemcpyAsync D2H
Do some work ...

CPU スレッドは、正しい順序でストリームを開始するように管理されます。したがって、cudaStreamWaitEventストリーム 1 のコピー完了イベントは、そのイベント (ストリーム 1) の前に (ストリーム 0 で) 呼び出されますcudaEventRecord。これにより、機能的なノーオペレーションが発生します。

イベントはこのままでは使えない気がします。目的の同期を実現する別の方法はありますか?

ところで、依存関係がいくつかあるため、ストリームの順序を逆にすることはできません。

API 呼び出し順序

リクエストに応じて、CUDA 呼び出しが発行される順序は次のとおりです。

//all on stream 0
cpy H2D
cudaEventRecord (event_copy_complete[0])
cudaStreamWaitEvent (event_copy_complete[1])
K<<< >>>    
cpy D2H

//all on stream 1
cpy H2D
cudaEventRecord (event_copy_complete[1])
cudaStreamWaitEvent (event_copy_complete[2])
K<<< >>>    
cpy D2H

//all on stream 2
cpy H2D
cudaEventRecord (event_copy_complete[2])
cudaStreamWaitEvent (event_copy_complete[3])
K<<< >>>    
cpy D2H
...

ご覧のとおり、 への呼び出しcudaStreamWaitEventは常に への呼び出しよりも先に行われcudaEventRecordます。

4

1 に答える 1

3

可能であれば、このすべての GPU 作業を単一の CPU スレッドからディスパッチする必要があります。そうすれば、(明白なことを述べるリスクがありますが)、API 呼び出しが実行される順序は、コードに表示される順序から推測できます。cudaEventRecord()とのcudaStreamWaitEvent()呼び出しはどちらも CUDA コンテキストに関連付けられた進行状況の値で動作するため、API 呼び出しの正確な順序が重要です。cudaEventRecord()現在の進行状況の値を記録し、それをインクリメントします。cudaStreamWaitEvent()現在の GPU がイベントの現在の進行状況の値を待機するコマンドを発行します。(そのため、呼び出しの順序を逆にすると、待機は効果的なノーオペレーションになります。)

API 呼び出しが異なるスレッドから行われている場合、目的の結果を生成するために多くのスレッド同期を行う必要があり、これもパフォーマンスに悪影響を及ぼします。実際、パフォーマンス上の理由から複数の CPU スレッドが必要な場合は、コードを再構築して CUDA 呼び出しを 1 つの CPU スレッドに委譲して順序を強制することができます。

于 2014-11-26T23:03:58.697 に答える