对于固定数据大小,双精度 CUDA 代码比单精度对应代码更快

Ran*_*Guy 1 c++ performance cuda

我已经在 CUDA 中实现了一个算法,并且双精度似乎比单精度运行得更快。

我知道通常单精度在 GPU 中速度更快。我的 GPU 是 Nvidia Geforce GT 650M。

算法伪代码如下:

for k to numIterations
    for j to numRowsOfAMatrix
        CUDAmemset(double arrayGPU)
        CUBLASdotproduct(double arrayGPU,double arrayGPU) [using cublasDdot]
        CUBLASdotproduct(double arrayGPU,double arrayGPU) [using cublasDdot]
        CUBLASscalarVectorMultiplication(scalarCPU,double arrayGPU) [using cublasDaxpy]
        CUBLASvectorSum(double arrayGPU,double arrayGPU) [using cublasDaxpy]
    end
end 
Run Code Online (Sandbox Code Playgroud)

我已经运行了一些具有以下属性的测试: 数组的长度为 2500。矩阵行长为2700。

我获得的时间如下:

50 次迭代:

单曲20.9960秒

双倍 20.1881 秒

200 次迭代:

单曲81.9562秒

双 78.9490 秒

500 次迭代:

单曲199.661秒

双倍 199.045 秒

1000 次迭代:

单曲413.129秒

双倍 396.205 秒

知道为什么双精度更快吗?

tal*_*ies 5

我不相信你可以说双精度版本比单精度版本更快。您自己的计时显示,50 次迭代大约需要 20 秒,500 次迭代大约需要 200 秒。那么问题就变成了为什么?

在我看来,您的代码似乎主要受 API 和 PCI-e 总线延迟的影响。在这种情况下,即使单精度和双精度之间的两倍内存带宽差异也可能无关紧要。如果每个数组只有大约 2500 长,那么计算的算术和设备内存事务部分与整体执行时间相比将绝对很小。

查看你的伪代码就知道原因了。在每次迭代中,两个点调用都会启动一个或多个内核,等待它们完成,然后从设备下载标量结果。然后,每个 axpy 调用都必须将标量上传到设备,然后启动内核。根据注释中的信息,这意味着您的代码可能对每个输入行执行两次阻塞内存复制和六次内核启动,并且每次迭代有 2700 个输入行。这意味着您的代码每次迭代执行10-15,000 次GPU API 调用,这是大量事务和 API 延迟(特别是如果您在 WDDM Windows 平台上执行此操作),最多不过几千次 FLOP 和少量每行数十 kb 的 GPU 内存访问。

在这种情况下,GPU 的峰值单精度比双精度算术吞吐量高 12 倍这一事实是无关紧要的,因为计算时间仅占您测量的总挂钟时间的一小部分。