【问题标题】:CUDA, float precisionCUDA,浮点精度
【发布时间】:2014-08-16 22:02:15
【问题描述】:

我在 Geforce GTX 580 (Fermi) 上使用 CUDA 4.0。我的数字小到 7.721155e-43 。我只想将它们相乘一次,或者更好地说我想计算 7.721155e-43 * 7.721155e-43 。

我的经验告诉我,我不能直接做到这一点。你能给我建议吗?我需要使用双精度吗?怎么样?

【问题讨论】:

  • 我认为您需要为此使用双精度,除非您可以将所有计算放大某个合适的因子?

标签: cuda floating-point gpu precision


【解决方案1】:

最小正规 IEEE 单精度数的量级约为 1.18e-38,最小的非正规数可将您降至约 1.40e-45。因此,大小为 7.82e-43 的操作数将仅包含大约 9 个非零位,这本身可能已经是一个问题,甚至在您进行乘法之前(其结果将在单精度下下溢为零)。因此,您可能还想查看产生这些微小数字的任何上游计算。

如果这些小数是数学表达式中的中间项,则将该表达式重写为不涉及微小中间项的数学等价表达式将是解决问题的一种方法。或者,您可以按 2 的幂的因子缩放一些操作数(以免因缩放而产生额外的舍入)。例如,按 2^24 = 16777216 缩放。

最后,您可以将部分计算切换为双精度。为此,只需引入 double 类型的临时变量,对它们执行计算,然后将最终结果转换回 float:

float r, f = 7.721155e-43f;
double d, t;

d = (double)f;   // explicit cast is not necessary, since converting to wider type
t = d * d;
[... more intermediate computation, leaving result in 't' ...]
r = (float)t;    // since conversion is to narrower type, cast will avoid warnings

【讨论】:

    【解决方案2】:

    在统计中,我们经常不得不处理最终非常小数字的可能性,标准技术是对所有事情都使用日志。然后对数尺度上的乘法只是加法。所有中间数字都存储为日志。事实上,它可能需要一些时间来适应——但即使在进行相对适度的计算时,替代方案也经常会失败。在 R 中(为了我的方便!)默认情况下使用双精度并打印 7 个有效数字:

    > 7.721155e-43 * 7.721155e-43
    [1] 5.961623e-85
    > exp(log(7.721155e-43) + log(7.721155e-43))
    [1] 5.961623e-85
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-10-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-10-03
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多