在CUDA中,为什么cudaMemcpy2D和cudaMallocPitch会消耗大量时间

时间:2014-06-18 08:06:53

标签: performance cuda gpu nvidia memory-bandwidth

正如标题中所提到的,我发现cudaMallocPitch()的功能消耗了大量时间,cudaMemcpy2D()消耗了相当长的时间。

以下是我正在使用的代码:

cudaMallocPitch((void **)(&SrcDst), &DeviceStride, Size.width * sizeof(float), Size.height);

cudaMemcpy2D(SrcDst, DeviceStride * sizeof(float), 
        ImgF1, StrideF * sizeof(float), 
        Size.width * sizeof(float), Size.height,
        cudaMemcpyHostToDevice);

在实施过程中,Size.widthSize.height均为4800. cudaMallocPitch()的耗时约为150-160毫秒(发生意外事件时多次测试),cudaMemcpy2D()消耗大约50ms。

CPU和GPU之间的内存带宽似乎不太可能如此受限,但我看不到代码中的任何错误,那么原因是什么?

顺便说一句,我使用的硬件是Intel I7-4770K CPU和Nvidia Geforce GTX 780(非常好的硬件没有错误)。

1 个答案:

答案 0 :(得分:3)

这里有许多因素可能影响绩效。

关于cudaMallocPitch,如果它恰好是您程序中的第一个cuda调用,则会产生额外的开销。

关于cudaMemcpy2D,这是通过一系列单独的memcpy操作完成的,每个2D区域一行(即4800个单独的DMA操作)。与普通cudaMemcpy操作(在单个DMA传输中传输整个数据区域)相比,这必然会产生额外的开销。此外,峰值传输速度仅在主机端存储器缓冲器被固定时实现。最后,您没有说明您的平台的任何信息。如果你在Windows上,那么WDDM将干扰此操作的完整传输性能,我们不知道你在哪种PCIE链接。

4800 * 4800 * 4 / 0.050 = 1.84GB / s,这是~3GB / s的重要部分,大致可用于跨PCIE 2.0的非固定传输。从上面列出的其他因素可以很容易地解释从3GB减少到1.84GB。

如果您想要完全传输性能,请使用固定内存,不要使用音调/ 2D传输。