1

我已经在 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 

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

我获得的时间如下:

50 次迭代:

单曲 20.9960 秒

双倍 20.1881 秒

200 次迭代:

单曲 81.9562 秒

双倍 78.9490 秒

500 次迭代:

单曲 199.661 秒

双倍 199.045 秒

1000 次迭代:

单曲 413.129 秒

双倍 396.205 秒

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

4

2 回答 2

4

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

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

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

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

于 2013-09-08T16:33:29.857 回答
0

两种算法(在您的情况下是单精度和双精度版本)之间的计算成本差异通常由渐近计算复杂度来衡量。由于 talonmies (延迟)解释的原因,对于固定(在您的情况下为小)向量长度,双精度可以具有与单精度相同的性能也就不足为奇了。要真正说明哪种算法更快,您应该根据向量长度分析时序N,从 的小到大的值开始N

另一个与 GPGPU 无关的例子是 FFT,它具有 的渐近复杂度O(NlogN),然后比 DFT 的“蛮力”求和更方便,后者是O(N^2)复杂度。但是,如果您比较 FFT 和“蛮力”DFT 求和对于非常低的 值的时间N,您会发现“蛮力”DFT 求和所需的时间最少。

于 2013-09-08T20:22:13.093 回答