2011-03-08 65 views
1

我写了一个代码,每个GPU使用多个主机(OpenMP)线程。每个线程都有自己的CUDA流来定购请求。它看起来非常类似于下面的代码:CUDA 4.0 RC - 每个GPU有许多主机线程 - cudaStreamQuery和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 = 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之后调用cudaSuccess,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

鉴于这是一个错误与功能问题,您最好在NVIDIA论坛上询问他们产品团队可以澄清它。 – 2011-03-08 14:58:51

+0

@Ade:我做到了 - http://forums.nvidia.com/index.php?showtopic=194982 – kokosing 2011-03-08 15:01:35

+0

你确定你已经在每个线程中正确初始化了cuda吗?你是否将正确的流传递给'cudaStreamSynchronize'(代码中没有参数)?另一方面,该流不必“准备就绪”来安排更多的内存传输和内核执行。这就是为什么它被称为流...... – LumpN 2011-03-08 17:33:24

回答

2

什么是下

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

你有样cudaMemcpyAsync任何功能那里,或只读存储器转移是在你的代码显示?这些异步函数可能会提前退出,即使代码尚未到达目的地。只有当内存传输成功时,cudaStreamQuery才会返回cudaSuccess

此外,hasJob()是否使用任何主机CUDA功能?

如果我没有弄错,在一个流中,不可能同时执行内核和内存传输。因此,仅当内核依赖于由不同流传输的数据时才需要调用cudaStreamQuery

+0

正如你所说那些是异步函数,所以我想知道天气提到的行为是一个正常的情况,这可能会发生时间又名。功能,并且它们可能比预期的更早退出。 列出了所有的cuda函数调用,hasJob()函数或代码准备工作只在常规C++中。 这里所有的流都是独立的,我只是想让他们中的哪一个完成它的工作,我想安排一个新的工作 - 动态和高效。 – kokosing 2011-03-09 10:01:40

1

先前没注意到:cudaStreamSynchronize()应该带参数(stream)。我不确定参数默认情况下您正在同步哪个流,可能是因为它默认为流0.

+0

你是对的,我忽略了它。我解决了这个问题。 – kokosing 2011-03-09 10:26:54

+0

它解决了您的问题,还是仅仅是问题代码中的错误,而不是真正的源代码?我问的原因是我相信你不应该经历你所描述的,我在指责NVIDIA之前正在考虑代码中可能出现的错误(尽管它们确实有很多错误)。 – CygnusX1 2011-03-09 10:30:36

+0

没有。只是在这里有问题。在我的代码中有适当的'cudaStreamSynchronize'和'stream'。 – kokosing 2011-03-09 13:11:04