The documentation here试图解释如何处理默认流。
给出如下代码(忽略分配错误):
char *ptr;
char source[1000000];
cudaMalloc((void**)&ptr, 1000000);
cudaMemcpyAsync(ptr, source, 1000000, cudaMemcpyHostToDevice);
myKernel<<<1000, 1000>>>(ptr);
是否有myKernel
在cudaMemcpyAsync
完成复制之前开始的风险?我认为“否”,因为这是文档中所述的“旧版默认流”。
但是,如果我使用CUDA_API_PER_THREAD_DEFAULT_STREAM
进行编译,会发生什么情况? “每线程默认流”的文本为:
每个线程的默认流是线程和
CUcontext
都本地的隐式流,并且不与其他流(如明确创建的流)同步。每个线程的默认流不是非阻塞流,如果在程序中使用了两者,它将与旧式默认流同步。
我认为这还可以,因为cudaMemcpyAsync
和myKernel
都有效地使用了CU_STREAM_PER_THREAD
;我正确吗?
我问的原因是我在内核中有一个非常奇怪的间歇性CUDA错误77,我只能通过cudaMemcpyAsync
来解释,即在调用myKernel
之前未完成,这意味着我不了解文档。但是,真正的代码太复杂,太专有了,无法制作MCVE。
答案 0 :(得分:1)
存在myKernel在cudaMemcpyAsync之前启动的风险 完成复制?我认为“否”,因为这是“旧版默认设置” 流”,如文档中所述。
没有,因为您注意到旧的默认流(流0)在所有情况下都处于阻塞状态,所以不会发生这种情况。
但是,如果我使用CUDA_API_PER_THREAD_DEFAULT_STREAM进行编译,会发生什么情况?
几乎没有任何变化。每个线程的默认流不会阻塞,因此其他流和使用其默认流的其他线程可以在上下文中并发操作。但是,这两个操作仍在同一流中,并且相对于彼此是顺序的。两种操作之间可能发生重叠的唯一方法是,如果source
是不可分页的内存分配,这会导致传输和内核执行之间出现重叠。否则,由于流的排序属性以及主机源内存施加的限制,它们将按顺序运行。
如果您确实存在怀疑可疑的意外操作重叠的问题,则应该可以通过分析来确认这一点。