为什么将数据从 CPU 传输到 GPU 而不是从 GPU 传输到 CPU 更快?
Why is it faster to transfer data from CPU to GPU rather than GPU to CPU?
我注意到将数据传输到最近的高端 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 内存、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
我不熟悉 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/
双向传输数据的时间相同。
我注意到将数据传输到最近的高端 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 内存、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
我不熟悉 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/
双向传输数据的时间相同。