考虑两段代码。
Snippet1
cudaStream_t stream1, stream2 ;
cudaStreamCreate(&stream1);
cudaStreamCreate(&stream2);
cudaMemcpyAsync( dst, src, size, dir, stream1 );
kernel<<<grid, block, 0, stream2>>>(...);
Snippet2
cudaStreamCreate(&stream1);
cudaStreamCreate(&stream2);
cudaMemcpy( dst, src, size, dir, stream1 );
kernel<<<grid, block, 0, stream2>>>(...);
在两个片段中,我发出了一个memcpy调用(snippet1异步和snippet2同步)
由于命令已发布到两个不同的流,根据我的理解,两种情况都可能存在重叠。
但是在Snippet2中,cudaMemcpy调用同步(又称阻塞)导致了一个矛盾的结论,即cudaMemcpy和内核调用将一个接一个地执行。
哪一个是正确的结论?
更紧凑地改写:当我们向流发出cudaMemcpy调用时,是否会阻止“整个代码”或阻止它发出的流?
答案 0 :(得分:0)
ArcheaSoftware部分正确。实际上,在操作完成之前,同步调用不会将控制权返回给CPU。从这种意义上说,只有在cudaMemcpy
调用返回之后,才会启动内核。但是,取决于您的缓冲区类型,内核可能会或可能无法使用通过cudaMemcpy
调用传输的数据。下面是一些示例:
示例1:
cudaMallocHost(&src, size);
cudaMalloc(&dst, size);
cudaMemcpy(dst, src, size, cudaMemcpyHostToDevice);
kernel<<<grid, block, 0, stream2>>>(...);
在这种情况下,内核可以使用从src
复制到dst
的数据。
示例2:
src = malloc(size);
cudaMalloc(&dst, size);
cudaMemcpy(dst, src, size, cudaMemcpyHostToDevice);
kernel<<<grid, block, 0, stream2>>>(...);
在这种情况下,cudaMemcpy
可以在实际将数据传输到设备之前返回。
cudaMemcpy
缓冲区)的 malloc
仅保证在将数据复制到源缓冲区的 out 中,也许复制到中间暂存缓冲区之前,通话返回。这是令人惊讶的行为,但在NVIDIA CUDA文档中已对此进行了定义。参考:https://docs.nvidia.com/cuda/cuda-runtime-api/api-sync-behavior.html#api-sync-behavior
通常,由于这种行为,我建议避免使用未注册的主机缓冲区。