代码之家  ›  专栏  ›  技术社区  ›  avgn

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

  •  12
  • avgn  · 技术社区  · 6 年前

    我注意到,将数据传输到最近的高端GPU比将数据收集回CPU要快。以下是使用mathworks技术支持向我提供的基准测试功能得出的结果,该功能运行在较旧的Nvidia K20和最新的Nvidia P100(带PCIE)上:

    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))
    

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

    2 回复  |  直到 6 年前
        1
  •  3
  •   Dev-iL    6 年前

    这是一个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
  •  1
  •   Helder Daniel    5 年前

    我不熟悉MatlabGPU工具箱,但我怀疑第二次传输(从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)事件测量时间。

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

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

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