1

1 つの GPU で多くのホスト (OpenMP) スレッドを使用するコードを作成しました。各スレッドには、要求を順序付けるための独自の CUDA ストリームがあります。以下のコードに非常によく似ています。

#pragma omp parallel for num_threads(STREAM_NUMBER)
for (int sid = 0; sid < STREAM_NUMBER; sid++) {
    cudaStream_t stream;
    cudaStreamCreate(&stream);

    while (hasJob()) {

        //... code to prepare job - dData, hData, dataSize etc

        cudaError_t streamStatus = cudaStreamQuery(stream);
        if (streamStatus == cudaSuccess) {
             cudaMemcpyAsync(dData, hData, dataSize, cudaMemcpyHostToDevice, stream);
             doTheJob<<<gridDim, blockDim, smSize, stream>>>(dData, dataSize);
        else {
             CUDA_CHECK(streamStatus);
        }
        cudaStreamSynchronize(stream);
    }
    cudaStreamDestroy(stream);
}

そして、私が多くの小さな仕事を得るまで、すべてが良かった. その場合、cudaStreamQuery はときどき cudaErrorNotReady を返します。これは、私が cudaStreamSynchronize を使用しているため、予期しないことです。今までは、cudaStreamSynchronize の後に呼び出された場合、cudaStreamQuery は常に cudaSuccess を返すと考えていました。残念ながら、cudaStreamQuery がまだ cudaErrorNotReady を返している場合でも、cudaStreamSynchronize が終了する可能性があるようです。

コードを次のように変更すると、すべてが正しく機能します。

#pragma omp parallel for num_threads(STREAM_NUMBER)
for (int sid = 0; sid < STREAM_NUMBER; sid++) {
    cudaStream_t stream;
    cudaStreamCreate(&stream);

    while (hasJob()) {

        //... code to prepare job - dData, hData, dataSize etc

        cudaError_t streamStatus;
        while ((streamStatus = cudaStreamQuery(stream)) == cudaErrorNotReady) {
             cudaStreamSynchronize();
        }
        if (streamStatus == cudaSuccess) {
             cudaMemcpyAsync(dData, hData, dataSize, cudaMemcpyHostToDevice, stream);
             doTheJob<<<gridDim, blockDim, smSize, stream>>>(dData, dataSize);
        else {
             CUDA_CHECK(streamStatus);
        }
        cudaStreamSynchronize(stream);
    }
    cudaStreamDestroy(stream);
}

だから私の質問は....それはバグですか、それとも機能ですか?

編集:JAVAに似ています

synchronize {
    while(waitCondition) {
         wait();
    }
}
4

2 に答える 2

2

下にあるもの

//... code to prepare job - dData, hData, dataSize etc

そこに何らかの機能がありますかcudaMemcpyAsync、それともあなたが示したコードに唯一のメモリ転送がありますか? これらは、コードがまだ宛先にない場合でも、非同期関数であり、早期に終了する可能性があります。When that occuredは、メモリ転送が成功した場合にのみcudaStreamQuery返されます。cudaSuccess

また、hasJob()ホスト CUDA 機能を使用していますか?

私が間違っていなければ、単一のストリームで、カーネル転送とメモリ転送の両方を実行することはできません。したがって、呼び出しcudaStreamQueryは、カーネルが別のストリームによって転送されるデータに依存する場合にのみ必要です。

于 2011-03-09T08:53:55.580 に答える
1

以前は気づかなかった:cudaStreamSynchronize()パラメータを取る必要があります(stream)。パラメータが省略されているときに同期しているストリームがわかりません。デフォルトでストリーム0になっている可能性があります。

于 2011-03-09T10:25:51.777 に答える