Matlab 为什么将数据从CPU传输到GPU比从GPU传输到CPU更快?

Matlab 为什么将数据从CPU传输到GPU比从GPU传输到CPU更快?,matlab,gpu,nvidia,tesla,Matlab,Gpu,Nvidia,Tesla,我注意到,将数据传输到最近的高端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 GP

我注意到,将数据传输到最近的高端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))
编辑:我们现在知道它不依赖于系统(参见注释)。我仍然想知道这种不对称的原因,或者它是否可以改变

这是一个CW为任何有兴趣张贴从他们的机器基准。我们鼓励投稿人留下他们的详细信息,以防将来对他们的结果产生疑问。

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

使用GeForce GTX 660 GPU。
实现了7.04747 GB/s的峰值发送速度
达到峰值采集速度3.11048 GB/s

撰稿人:戴夫·伊尔



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

使用Quadro P6000 GPU。
实现了1.43346 GB/s的峰值发送速度
实现了1.32355 GB/s的峰值采集速度

贡献者:Dev iL

我不熟悉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程序问题:

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

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

cudaDeviceSynchronize()

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

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

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

在这篇关于优化数据传输的文章中,同样在C中,事件用于测量数据传输时间:


在两个方向上传输数据的时间是相同的。

为了回答您的第二个问题,我可以在Quadro M5000 GPU上重现结果,这里的峰值发送速度为10.0442 GB/s,峰值采集速度为3.66208 GB/s。所以它看起来不像是依赖于系统的。谢谢!我也在其他系统上试用过,结果也差不多。因此,现在我们可以确认它不依赖于系统。考虑到GPU主要设计用于在屏幕上生成图形,将上传速度作为优先于下载速度是有意义的。我认为为了完整性,该基准测试也应在不同的环境/语言中进行,以排除与MATLAB相关的怪癖。峰值是否代表速度?我肯定会更相信平均水平。
% 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);