【问题标题】:Why is it faster to transfer data from CPU to GPU rather than GPU to CPU?为什么将数据从 CPU 传输到 GPU 比从 GPU 传输到 CPU 更快?
【发布时间】:2018-10-22 10:46:19
【问题描述】:

我注意到将数据传输到最近的高端 GPU 比将数据收集回 CPU 更快。以下是使用 mathworks 技术支持提供给我的基准测试函数在较旧的 Nvidia K20 和最近的带有 PCIE 的 Nvidia P100 上运行的结果:

Using a Tesla P100-PCIE-12GB GPU.
Achieved peak send speed of 11.042 GB/s
Achieved peak gather speed of 4.20609 GB/s

Using a Tesla K20m GPU.
Achieved peak send speed of 2.5269 GB/s
Achieved peak gather speed of 2.52399 GB/s

我在下面附上了基准函数以供参考。 P100不对称的原因是什么?这个系统是依赖于它还是最近高端 GPU 的标准?采集速度可以提高吗?

gpu = gpuDevice();
fprintf('Using a %s GPU.\n', gpu.Name)
sizeOfDouble = 8; % Each double-precision number needs 8 bytes of storage
sizes = power(2, 14:28);

sendTimes = inf(size(sizes));
gatherTimes = inf(size(sizes));
for ii=1:numel(sizes)
    numElements = sizes(ii)/sizeOfDouble;
    hostData = randi([0 9], numElements, 1);
    gpuData = randi([0 9], numElements, 1, 'gpuArray');
    % Time sending to GPU
    sendFcn = @() gpuArray(hostData);
    sendTimes(ii) = gputimeit(sendFcn);
    % Time gathering back from GPU
    gatherFcn = @() gather(gpuData);
    gatherTimes(ii) = gputimeit(gatherFcn);
end
sendBandwidth = (sizes./sendTimes)/1e9;
[maxSendBandwidth,maxSendIdx] = max(sendBandwidth);
fprintf('Achieved peak send speed of %g GB/s\n',maxSendBandwidth)
gatherBandwidth = (sizes./gatherTimes)/1e9;
[maxGatherBandwidth,maxGatherIdx] = max(gatherBandwidth);
fprintf('Achieved peak gather speed of %g GB/s\n',max(gatherBandwidth))

编辑:我们现在知道它不依赖于系统(参见 cmets)。我仍然想知道不对称的原因,或者它是否可以改变。

【问题讨论】:

  • 要回答你的第二个问题,我可以在 Quadro M5000 GPU 上重现结果,这里我的峰值发送速度为 10.0442 GB/s,峰值收集速度为 3.66208 GB/s。所以它似乎并不依赖于系统。
  • 谢谢!我也在其他系统上尝试过,结果相似。所以现在我们可以确认它不依赖于系统。
  • 考虑到 GPU 主要用于在屏幕上生成图形,因此将上传速度优先于下载速度是有意义的。
  • 我认为为了完整起见,这个基准测试也应该在不同的环境/语言中完成,以排除与 MATLAB 相关的怪癖。
  • 峰值代表速度吗?我肯定会更相信平均值。

标签: matlab gpu nvidia tesla


【解决方案1】:

对于任何有兴趣从他们的机器发布基准的人来说,这是一个 CW。鼓励贡献者留下他们的详细信息,以防将来出现关于他们的结果的问题。



系统:Win10,32GB DDR4-2400Mhz RAM,i7 6700K。 MATLAB:R2018a。

Using a GeForce GTX 660 GPU.
Achieved peak send speed of 7.04747 GB/s
Achieved peak gather speed of 3.11048 GB/s

Warning: The measured time for F may be inaccurate because it is running too fast. Try measuring something that takes
longer. 

贡献者:Dev-iL



系统:Win7,32GB RAM,i7 4790K。 MATLAB:R2018a。

Using a Quadro P6000 GPU.
Achieved peak send speed of 1.43346 GB/s
Achieved peak gather speed of 1.32355 GB/s

贡献者:Dev-iL

【讨论】:

    【解决方案2】:

    我不熟悉 Matlab GPU 工具箱,但我怀疑第二次传输(从 GPU 取回数据)在第一次传输结束之前开始。

    % Time sending to GPU
    sendFcn = @() gpuArray(hostData);
    sendTimes(ii) = gputimeit(sendFcn);
    %
    %No synchronization here
    %
    % Time gathering back from GPU
    gatherFcn = @() gather(gpuData);
    gatherTimes(ii) = gputimeit(gatherFcn);
    

    这里发布了一个类似的 C 程序问题:

    copy from GPU to CPU is slower than copying CPU to GPU

    在这种情况下,在 GPU 上启动线程并从 GPU 取回结果数据后没有显式同步。 因此,在 C cudaMemcpy() 中取回数据的函数必须等待 GPU 结束先前启动的线程,然后才能传输数据,从而增加了为数据传输测量的时间。

    使用 Cuda C API,可以强制 CPU 等待 GPU 结束先前启动的线程,方法是:

    cudaDeviceSynchronize();

    然后才开始测量传回数据的时间。

    也许在 Matlab 中也有一些同步原语。

    同样在同一个答案中,建议使用(Cuda)事件来测量时间。

    在这篇关于优化数据传输的 POST 中,对不起,在 C 中,事件用于测量数据传输时间:

    https://devblogs.nvidia.com/how-optimize-data-transfers-cuda-cc/

    双向传输数据的时间相同。

    【讨论】:

      猜你喜欢
      • 2013-02-07
      • 1970-01-01
      • 2012-10-31
      • 2012-07-07
      • 2019-11-19
      • 1970-01-01
      • 2011-09-23
      • 2022-01-01
      • 2015-07-02
      相关资源
      最近更新 更多