我的项目将有多个线程,每个线程在不同的cudaStream上发出内核执行。其他一些线程将使用存储在队列中的结果。这里有一些伪代码:
while(true) {
cudaMemcpyAsync(d_mem, h_mem, some_stream)
kernel_launch(some_stream)
cudaMemcpyAsync(h_queue_results[i++], d_result, some_stream)
}
在第一个cudaMemcpyAsync返回后重用h_mem是否安全?或者我应该使用N个主机缓冲区来发出gpu计算?
如何知道何时可以重用h_mem?我应该使用cudaevents进行一些同步吗?
顺便说一句。 h_mem是主机固定的。如果它是可分页的,我可以重新使用h_mem吗?从我在这里看到的,似乎我可以在memcpyasync返回后重新使用,我是对的吗?
异步
用于从可分页主机内存到设备内存,主机内存的传输 被立即复制到临时缓冲区(没有设备同步 执行)。一旦可分页缓冲区有,该函数将返回 已复制到暂存内存。 DMA转移到最终 目的地可能尚未完成。用于固定主机之间的传输 内存和设备内存,该功能完全异步。对于 从设备内存传输到可分页的主机内存,该功能 只有在副本完成后才会返回。对于所有其他转移, 该函数是完全异步的。如果必须首先是可分页内存 分阶段固定内存,这将与a异步处理 工人线程。对于从任何主机内存到任何主机内存的传输, 该功能与主机完全同步。
谢谢!
答案 0 :(得分:1)
为了获得复制/计算重叠,您必须使用固定内存。其原因包含在您摘录的段落中。大概是你的多流方法的全部原因是复制/计算重叠,所以我不认为正确的答案是切换到使用可分页的内存缓冲区。
关于您的问题,假设h_mem
仅用作您在此处显示的伪代码的源缓冲区(即其中的数据仅参与那一个cudaMemcpyAsync
调用) ,一旦该流中的 next cuda操作开始,则不再需要h_mem缓冲区。因此,如果您的kernel_launch
是实际kernel<<<...>>>(...)
,那么一旦kernel
开始,您就可以确信之前的cudaMemcpyAsync
已完成。
您可以将cudaEvents与cudaEventSynchronize()
或cudaStreamWaitEvent()
一起使用,也可以直接在流中使用cudaStreamSynchronize()
。例如,如果您在已显示的流伪代码中的某处有cudaStreamSynchronize()
调用,并且它位于cudaMemcpyAsync
调用之后,那么cudaStreamSynchronize()
调用之后的任何代码都将保证正在执行cudaMemcpyAsync()
电话完成后。我引用的所有电话都记录在usual place。