我写了一个代码,每个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();
}
}
答案 0 :(得分:2)
下的内容
//... code to prepare job - dData, hData, dataSize etc
你有没有cudaMemcpyAsync
种类的功能,或者你所展示的代码中只有内存传输?即使代码不在目的地,这些异步函数也可能提前退出。发生这种情况时,cudaStreamQuery
仅在内存传输成功时返回cudaSuccess
。
此外,hasJob()
是否使用任何主机CUDA功能?
如果我没有弄错,在单个流中,不可能同时执行内核和内存传输。因此,仅当内核依赖于由不同流传输的数据时,才需要调用cudaStreamQuery
。
答案 1 :(得分:1)
之前没有注意到:cudaStreamSynchronize()
应该使用参数(stream)
。当参数被省略时,我不确定您正在同步哪个流,可能是默认为流0。