我有一个程序,我在GPU上做了一堆计算,然后我在CPU上执行这些结果的内存操作,然后我接下一批数据并全部执行相同操作。现在,如果我可以进行第一组计算,然后从第二批开始,而我的CPU在内存操作中转动,那将会快得多。我该怎么做?
答案 0 :(得分:5)
所有CUDA内核调用(例如function<<<blocks, threads>>>()
)都是异步的 - 它们立即将控制权返回给调用主机线程。因此,只需在内核调用之后使CPU工作,就可以始终与GPU工作并行执行CPU工作。
如果您还需要同时将数据从GPU传输到CPU,则需要将deviceOverlap
字段设置为true的GPU(使用cudaGetDeviceProperties()
检查),并且您需要从单独的CUDA流中使用cudaMemcpyAsync()
。
有一些示例可以在NVIDIA CUDA SDK中演示此功能 - 例如“simpleStreams”和“asyncAPI”示例。
答案 1 :(得分:2)
基本思想可以是这样的:
在GPU上进行第一批计算
输入循环:{
将设备内存中的结果复制到主机内存
在GPU中进行下一批计算(内核启动是同步的,控件立即返回CPU)
在CPU上处理上一次迭代的结果
}
将上次迭代的结果从设备mem复制到主机mem
使用cudaMemcpyAsync,cudaStream和cudaEvent可以更好地控制CPU和GPU之间的异步工作。
正如@harrism所说,你需要你的设备支持deviceOverlap来同时执行内存传输和执行内核,但即使它没有该选项,你至少可以与CPU上的其他计算异步执行内核。 / p>
编辑:不推荐使用deviceOverlap,应该使用asyncEngineCount属性。