CUDAマニュアルから、私cudaStreamQuery
は非同期ストリームで動作することを知っています:
非同期ストリームに完了ステータスを照会します。
「デフォルトストリーム」での動作をテストする簡単なプログラムを作成します。
#include <cstdlib>
#include <iostream>
#define cudaSafeCall(call) \
do {\
cudaError_t err = call;\
if (cudaSuccess != err) \
{\
std::cerr << "CUDA error in " << __FILE__ << "(" << __LINE__ << "): " \
<< cudaGetErrorString(err) << '\n';\
exit(EXIT_FAILURE);\
}\
} while(0)
int main(void)
{
int N = 1<<20;
float *x, *d_x;
x = (float*)malloc(N*sizeof(float));
cudaSafeCall(cudaMalloc(&d_x, N*sizeof(float)));
cudaSafeCall(cudaMemcpy(d_x, x, N*sizeof(float), cudaMemcpyDefault));
cudaSafeCall(cudaStreamQuery(0));
cudaSafeCall(cudaFree(d_x));
free(x);
return 0;
}
ビルドして実行します。
$ nvcc sync_test.cu -o sync_test
$ ./sync_test
CUDA error in sync_test.cu(25): device not ready
とのcudaStreamSynchronize(0);
間に追加した後、エラーは消えました:cudaMemcpy
cudaStreamQuery
cudaSafeCall(cudaMemcpy(d_x, x, N*sizeof(float), cudaMemcpyDefault));
cudaSafeCall(cudaStreamSynchronize(0));
cudaSafeCall(cudaStreamQuery(0));
私は少し混乱しています:
a)cudaMemcpy()
ホストコードと同期しているので、cudaMemcpy
返された後、このストリームのコピー作業を行う必要がありcudaStreamQuery(0)
ますが、最初のケースでエラーが返されるのはなぜですか?
b)cudaStreamQuery
デフォルトのストリームではなく、非同期ストリームでのみ機能するcudaStreamQuery
場合、2番目のケースでエラーが返されないのはなぜですか?
あなたのステートメントa)は、サンプルコードの特定のケースに対して完全に正確ではありません。
a)
cudaMemcpy()
ホストコードと同期しているため、cudaMemcpy
返された後、このストリームのコピー作業を実行する必要があります。
ドキュメントのためcudaMemcpy
の状態:
この関数は、ほとんどのユースケースで同期動作を示します。
同期リンクをクリックすると、正確な動作をさらに定義するページに移動します。あなたはそのページ全体を読みたいかもしれません、それはそれほど長くはありません。同期の定義から2つのポイントを抜粋します。
- ページング可能なホストメモリからデバイスメモリへの転送の場合、コピーが開始される前にストリーム同期が実行されます。デバイスメモリへのDMA転送のためにページング可能バッファがステージングメモリにコピーされると、関数は戻りますが、最終宛先へのDMAが完了していない可能性があります。(強調を追加)
そして:
- デバイスからページング可能または固定されたホストメモリへの転送の場合、関数はコピーが完了したときにのみ戻ります。
あなたのコードは最初の抜粋(上記の項目2)に適合します。その転送タイプ(ホストからデバイス)は、コピーが完全に完了する前に戻る可能性があります。
cudaMemcpy
例でポインタの順序を逆にして、コピーの方向を逆にすると、2番目の抜粋(上記の項目4)に分類されます。その場合、転送が完了することが保証され、実際にエラーレポートがコードから消えます。
この動作は可能であり、ドキュメントで説明されています。
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加