我试图将内核执行与memcpyasync D2H重叠,但它不起作用。我有N组元素。每组有64个元素,可以并行处理。虽然由于数据依赖性,组的处理必须是顺序的。也就是说,必须在处理组i-1的元素之后处理组i的元素。处理组中的每个元素会产生一个必须从GPU传输到CPU的输出。为了重叠这个D2H数据传输,我将一个组的元素划分为多个块,以便可以使用流重叠给定块上的内核执行和D2H MemcpyAsync。我使用以下伪代码使用K流处理N组元素。
groupId=0;
`while( groupId< N){`
for(i=0;i<K;++i)
// all stream must wait to complete the kernel execution
of last stream before starting of the processing of next group
if( groupId!=0)
cudaStreamWaitEvent(stream[K-1],syncEvent,0)
kernelA<<< >>>(----,----,----);
CUDAEventRecord(syncEvent,stream[K-1]);
cudaMemcpyAsync(,,,cudaMemcpyDeviceToHost,stream[i]);
}
groupId++
}
当我使用两个流时,则存在一些重叠,而当我增加流的数量时,没有重叠,如下图所示。 Processing of 64 elements using two stream.
Processing of 64 elements using four stream
请解释为什么D2H数据传输没有完全重叠。 此外,在四个流的情况下,每个流的内核用16个线程块调用,每个线程块大小为128个线程。从概念上讲,两个流应该同时执行(每个都在SM上),因为GPU上有足够的资源可用。但是,不同流的内核执行没有并发性(图2)。在这种情况下,没有并发的原因是什么?
答案 0 :(得分:1)
64 字节的传输太短而不能与任何东西重叠 - 在完全PCIe 2.0速度(大约6GB / s)下,实际传输需要大约10 nano 秒。这将是截图缩放比例下探查器时间轴上大约1/1000像素宽度的值。条和间隙的有限宽度完全是由于每次传输的开销(设置等)。
您希望传输兆字节的顺序,以便能够与计算重叠传输。