OpenCL减少结果错误的大浮点数

时间:2015-01-05 15:34:11

标签: opencl gpu reduction

我使用AMD's two-stage reduction example使用浮点精度计算0到65 536之间所有数字的总和。不幸的是,结果不正确。但是,当我修改我的代码时,我计算了65 536个较小数字的总和(例如1),结果是正确的。

我无法在代码中发现任何错误。由于浮动类型,我可能会得到错误的结果吗?如果是这种情况,解决问题的最佳方法是什么?

2 个答案:

答案 0 :(得分:2)

这是副作用"使用有限精度CPU或GPU来汇总浮点数。精度取决于算法和值相加的顺序。背后的理论和实践在Nicholas J,Higham的论文中有所解释

浮点求和的准确性

http://citeseerx.ist.psu.edu/viewdoc/download;jsessionid=7AECC0D6458288CD6E4488AD63A33D5D?doi=10.1.1.43.3535&rep=rep1&type=pdf

修复方法是使用更智能的算法,如Kahan求和算法

https://en.wikipedia.org/wiki/Kahan_summation_algorithm

高海姆的论文也有其他选择。

这个问题说明了基准测试的本质,基准测试的第一条规则是获得 正确答案,使用现实数据!

答案 1 :(得分:1)

您的内核或主机应用程序的编码可能没有错误。问题在于单精度浮点。

正确的总和是:65537 * 32768 = 2147516416,它需要31位来表示二进制(10000000000000001000000000000000)。 32位浮点数只能精确保持整数2 ^ 24。

  

"绝对值小于[2 ^ 24]的任何整数都可以用单精度格式精确表示"   "Floating Point" article, wikipedia

这就是为什么在小于或等于2 ^ 24时得到正确的总和。如果使用单精度进行完整求和,无论您在哪个设备上执行内核,最终都会失去准确性。您可以采取一些措施来获得正确的答案:

  • 如果您的平台支持,请使用double而不是float
  • use int或unsigned int
  • 求和一组较小的数字,例如:0 + 1 + 2 + ... + 4095 + 4096 =(2 ^ 23 + 2 ^ 11)

Read more about single precision here.