Cuda:内核启动队列

时间:2012-10-05 20:49:39

标签: cuda

我没有找到有关内核启动操作机制的更多信息。 API说要查看CudaProgGuide。而且我也找不到那么多 由于内核执行是异步的,并且一些机器支持并发执行,因此我认为内核有一个队列。

    Host code:      
    1. malloc(hostArry, ......);  
    2. cudaMalloc(deviceArry, .....);  
    3. cudaMemcpy(deviceArry, hostArry, ... hostToDevice);
    4. kernelA<<<1,300>>>(int, int);  
    5. kernelB<<<10,2>>>(float, int));  
    6. cudaMemcpy(hostArry, deviceArry, ... deviceToHost);  
    7. cudaFree(deviceArry);

第3行是同步的。 4号线和4号线5是异步的,并且机器支持并发执行。所以在某些时候,这两个内核都在GPU上运行。 (在kernelA完成之前,kernelB有可能启动并完成。)当发生这种情况时,主机正在执行第6行。第6行与复制操作是同步的,但没有什么能阻止它在kernelA之前执行或者kernelB已经完成了。

1)GPU中是否有内核队列? (GPU是否阻止/停止主机?)
2)主机如何知道内核已经完成,将设备的结果发送到主机是否“安全”?

2 个答案:

答案 0 :(得分:4)

是的,GPU上有各种队列,驱动程序可以管理这些队列。

异步调用会立即或多或少地返回。在操作完成之前,同步调用不会返回。内核调用是异步的。如果它们是异步的,则大多数其他CUDA运行时API调用由后缀Async指定。所以回答你的问题:

  

1)GPU中是否有内核队列? (GPU会阻塞/停止主机吗?)

有各种队列。 GPU在同步调用中阻塞/停止主机,但内核启动不是同步操作。它在内核完成之前立即返回,也许在内核启动之前返回。将操作启动到单个流中时,该流中的所有CUDA操作都是序列化。因此,即使内核启动是异步的,您也不会观察到发送到同一个流的两个内核的重叠执行,因为CUDA子系统保证流中的给定CUDA操作在所有先前的CUDA操作之前都不会启动相同的流已经完成。对于空流还有其他特定规则(如果您没有在代码中明确地调用流,则使用您正在使用的流),但前面的描述足以理解此问题。

  

2)主机如何知道内核已经完成,将设备的结果放到主机上是“安全的”?

由于将结果从设备传输到主机的操作是 CUDA 调用(cudaMemcpy ...),并且它在与前面的操作相同的流中发布,设备和< em> CUDA驱动程序管理cuda调用的执行顺序,以便在发出到同一个流的所有先前CUDA调用完成之前,cudaMemcpy不会开始。因此,即使您使用cudaMemcpy,在内核调用完成之后,保证在相同流中的内核调用之后发出的cudaMemcpyAsync也不会启动。

答案 1 :(得分:0)

您可以在内核调用后使用cudaDeviceSynchronize()来保证为设备请求的所有先前任务都已完成。 如果kernelB的结果与kernelA上的结果无关,则可以在内存复制操作之前设置此函数。如果没有,则需要在调用kernelB之前阻塞设备,从而导致两次阻塞操作。