10

私はコードに非常に似たものを持っています:

int k, no_streams = 4;
cudaStream_t stream[no_streams];
for(k = 0; k < no_streams; k++) cudaStreamCreate(&stream[k]);

cudaMalloc(&g_in,  size1*no_streams);
cudaMalloc(&g_out, size2*no_streams);

for (k = 0; k < no_streams; k++)
  cudaMemcpyAsync(g_in+k*size1/sizeof(float), h_ptr_in[k], size1, cudaMemcpyHostToDevice, stream[k]);

for (k = 0; k < no_streams; k++)
  mykernel<<<dimGrid, dimBlock, 0, stream[k]>>>(g_in+k*size1/sizeof(float), g_out+k*size2/sizeof(float));

for (k = 0; k < no_streams; k++)
  cudaMemcpyAsync(h_ptr_out[k], g_out+k*size2/sizeof(float), size2, cudaMemcpyDeviceToHost, stream[k]);

cudaThreadSynchronize();

cudaFree(g_in);
cudaFree(g_out);

'h_ptr_in'および'h_ptr_out'は、cudaMallocHost(フラグなし)で割り当てられたポインターの配列です。

問題は、ストリームがオーバーラップしないことです。ビジュアルプロファイラーでは、最初のストリームからのカーネル実行が2番目のストリームからのコピー(H2D)とオーバーラップしているのを確認できますが、他には何もオーバーラップしていません。

2つのカーネルを実行するためのリソースがないかもしれませんが(私はそう思います)、少なくともカーネルの実行とコピーは重複しているはずですよね?そして、3つすべて(H2Dのコピー、カーネルの実行、D2Hのコピー)を同じforループ内に配置すると、それらのいずれも重複しません...

助けてください、これを引き起こしている可能性がありますか?

私は実行しています:

Ubuntu 10.04 x64

デバイス:「GeForceGTX460」(CUDAドライバーバージョン:3.20、CUDAランタイムバージョン:3.20、CUDA機能メジャー/マイナーバージョン番号:2.1、同時コピーおよび実行:はい、同時カーネル実行:はい)

4

2 に答える 2

7

NVIDIAフォーラムのこの投稿によると、プロファイラーはストリーミングをシリアル化して正確なタイミングデータを取得します。タイミングがずれていると思われる場合は、CUDAイベントを使用していることを確認してください...

最近ストリーミングを試していますが、SDKの「simpleMultiCopy」の例は、特に適切なロジックと同期で非常に役立つことがわかりました。

于 2011-05-20T14:42:21.890 に答える
3

カーネルがカーネル(並行カーネル)とオーバーラップすることを確認したい場合は、CUDA5.0Toolkitに付属のCUDAVisualProfiler5.0を使用する必要があります。以前のプロファイラーはこれができないと思います。また、カーネルとmemcpyのオーバーラップも表示されます。

于 2012-08-14T12:53:30.123 に答える