0

私のプロジェクトには複数のスレッドがあり、それぞれが異なる cudaStreams でカーネル実行を発行します。他のいくつかのスレッドは、キューに格納される結果を消費します ここにいくつかの疑似コードがあります:

while(true) {
  cudaMemcpyAsync(d_mem, h_mem, some_stream) 
  kernel_launch(some_stream)
  cudaMemcpyAsync(h_queue_results[i++], d_result, some_stream)
}

最初の cudaMemcpyAsync が戻った後に h_mem を再利用しても安全ですか? または、gpu 計算を発行するために N 個のホスト バッファーを使用する必要がありますか?

h_mem をいつ再利用できるかを知る方法は? cudaevents を使用して同期を行う必要がありますか?

ところで。h_mem はホスト固定です。ページング可能な場合、すぐに h_mem を再利用できますか? 私がここで読んだことから、memcpyasync が戻った後、すぐに再利用できるようです。

非同期

ページング可能なホスト メモリからデバイス メモリへの転送の場合、ホスト メモリはすぐにステージング バッファにコピーされます (デバイスの同期は実行されません)。ページング可能なバッファがステージング メモリにコピーされると、関数は戻ります。最終宛先への DMA 転送が完了していない可能性があります。固定されたホスト メモリとデバイス メモリ間の転送では、関数は完全に非同期です。デバイス メモリからページング可能なホスト メモリへの転送の場合、関数はコピーが完了した後にのみ戻ります。他のすべての転送では、関数は完全に非同期です。ページング可能なメモリを最初に固定メモリにステージングする必要がある場合、これはワーカー スレッドで非同期に処理されます。任意のホスト メモリから任意のホスト メモリへの転送の場合、関数はホストに関して完全に同期します。

MemcpyAsynchronousBehavior

ありがとう!

4

1 に答える 1

1

コピー/計算のオーバーラップを取得するには、固定メモリを使用する必要があります。その理由は、あなたが抜粋した段落に含まれています。おそらく、マルチストリーム アプローチの全体的な理由はコピー/計算のオーバーラップのためであるため、正しい答えはページング可能なメモリ バッファーの使用に切り替えることではないと思います。

あなたの質問に関して、あなたh_memがここに示した疑似コードのソースバッファとしてのみ使用されると仮定すると(つまり、その中のデータはその1つの呼び出しにのみ参加します)、h_memバッファは、次のcuda操作が行われるcudaMemcpyAsyncと不要になりますその流れが始まります。したがって、あなたが実際のであった場合、一度開始すると、前のが完了していることを確認できます。kernel_launchkernel<<<...>>>(...)kernelcudaMemcpyAsync

cudaEventSynchronize()またはでcudaEvents を使用することも、ストリームで直接cudaStreamWaitEvent()使用することもできます。cudaStreamSynchronize()たとえば、cudaStreamSynchronize()表示したストリーム疑似コードのどこかに呼び出しがあり、それが呼び出しの後であるcudaMemcpyAsync場合、呼び出しの後のコードはcudaStreamSynchronize()、呼び出しの完了後に実行されることが保証されますcudaMemcpyAsync()。私が参照した呼び出しはすべて、通常の場所に文書化されています。

于 2013-04-17T14:03:15.730 に答える