CUDA、浮点精度
我在 Geforce GTX 580 (Fermi) 上使用 CUDA 4.0。我的数字小到 7.721155e-43 。我想将它们相乘一次或者更好地说我想计算 7.721155e-43 * 7.721155e-43 。
我的经验告诉我,我不能直接做到这一点。您能给我建议吗?我需要使用双精度吗?如何?
I am using CUDA 4.0 on Geforce GTX 580 (Fermi) . I have numbers as small as 7.721155e-43 . I want to multiply them with each other just once or better say I want to calculate 7.721155e-43 * 7.721155e-43 .
My experience showed me I can't do it just straight forward. Could you please give me suggestion? Do I need to use double precision? How?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
最小的标准 IEEE 单精度数的大小约为 1.18e-38,最小的非标准数可降至约 1.40e-45。因此,大小为 7.82e-43 的操作数将仅包含大约 9 个非零位,这本身可能已经是一个问题,甚至在进行乘法之前(其结果将在单精度下下溢到零)。因此,您可能还想查看产生这些微小数字的任何上游计算。
如果这些小数字是数学表达式中的中间项,则将该表达式重写为不涉及微小中间项的数学等效表达式将是解决该问题的一种方法。或者,您可以按 2 的幂的因子缩放某些操作数(以免因缩放而产生额外的舍入)。例如,缩放 2^24 = 16777216。
最后,您可以将部分计算切换为双精度。为此,只需引入 double 类型的临时变量,对它们执行计算,然后将最终结果转换回 float:
The magnitude of the smallest normal IEEE single-precision number is about 1.18e-38, the smallest denormal gets you down to about 1.40e-45. As a consequece an operand of magnitude 7.82e-43 will comprise only about 9 non-zero bits, which in itself may already be a problem, even before you get to the multiplication (whose result will underflow to zero in single precision). So you may also want to look at any up-stream computation that produces these tiny numbers.
If these small numbers are intermediate terms in a mathematical expression, rewriting that expression into a mathematically equivalent one that does not involve tiny intermediates would be one way of addressing the issue. Or you could scale some operands by factors that are powers of two (so as to not incur additional round-off due to the scaling). For example, scale by 2^24 = 16777216.
Lastly, you can switch part of the computation to double precision. To do so, simply introduce temporary variables of type double, perform the computation on them, then convert the final result back to float:
在统计学中,我们经常不得不处理最终非常很小的数字的可能性,而标准技术是对所有事情都使用日志。那么对数尺度上的乘法就是加法。所有中间数字都存储为日志。事实上,这可能需要一些时间来适应 - 但即使在进行相对适度的计算时,替代方案也常常会失败。在 R 中(为了我的方便!),默认情况下使用双精度数并打印 7 个有效数字:
In statistics we often have to work with likelihoods that end up being very small numbers and the standard technique is to use logs for everything. Then multiplication on a log scale is just addition. All intermediate numbers are stored as logs. Indeed it can take a bit of getting used to - but the alternative will often fail even when doing relatively modest computations. In R (for my convenience!) which uses doubles and prints 7 significant figures by default btw: