【问题标题】:Computing RD(sqrt(x)) with a FPU in RU mode在 RU 模式下使用 FPU 计算 RD(sqrt(x))
【发布时间】:2023-11-19 22:14:01
【问题描述】:

浮点边界的区间可用于过度近似实数集,只要任何结果区间的上限是向上舍入计算的,而下限是向下舍入计算的。

一个推荐的技巧是实际计算下界的否定。这允许 FPU 始终保持向上舍入(例如,“Handbook of Floating-Point Arithmetic”,2.9.2)。

这适用于加法和乘法。另一方面,平方根运算在加法和乘法方面是不对称的。

我突然想到,为了计算 sqrtRD,对于下限,以下习语尽管很复杂,但在具有 IEEE 754 双精度和 @ 的普通平台上可能会更快987654321@定义为0比改变舍入模式两次:

#include <fenv.h>
#include <math.h>
#pragma STDC FENV_ACCESS ON
…
/* assumes round-upwards */
double sqrt_rd(double l) { 
  feclearexcept(FE_INEXACT);
  double candidate = sqrt(l);
  if (fetestexcept(FE_INEXACT))
    return nextafter(candidate, 0);
  return candidate;
}

我想知道这是否更好,以及它是否是最快的。作为一种可能的替代方案,但仍不一定是最快的,在我看来 FMARU(candidate, Candidate, -l) 可能并不总是准确的(因为有向舍入),但可能是在 0 左右足够准确,以便以下工作:

/* assumes round-upwards */
double sqrt_rd(double l) { 
  double candidate = sqrt(l);
  if (fma(candidate, candidate, -l) != 0.0)
    return nextafter(candidate, 0);
  return candidate;
}

还有什么其他廉价的方法可以检测到sqrt 是不准确的? 在设置为向上舍入的现代 FPU 上,哪种浮点运算组合可以最快地计算 sqrt_rd

【问题讨论】:

  • 我怀疑这取决于实现和实际环境。
  • @Olaf 我已经更新了这个问题,其中包含这是针对具有 IEEE 754 双精度和 FLT_EVAL_METHOD=0 的平台的信息。
  • 这没有多大帮助。 “实现”是编译器,“环境”是目标平台/架构。展示极端情况:可能没有可用的 FPU,或者整个函数可能导致单个 FPU 指令。
  • @Olaf 任何喜欢对其解决方案进行基准测试的人都可以使用 Haswell 处理器和 GCC 5.3.0。我希望有一些对于如此广泛的平台来说显然是一种收益的东西,它不需要进行基准测试,比如最初的“将 mult_rd(x, y) 计算为 -mult_ru(-x, y)”技巧。

标签: c floating-point c99 ieee-754


【解决方案1】:

我认为你应该可以使用:

/* assumes round-upwards */
double sqrt_rd(double l) { 
  double u = sqrt(l);
  double w = u*u;
  if (w != l)
    return nextafter(u, 0);
  return u;
}

这里的理由是如果u不精确,那么它将严格大于√l,这反过来意味着w >= u2 > @ 987654326@(因为w也是在RU模式下计算的)。如果u 是准确的,那么w 也是准确的(因为我们知道它必须可以表示为双精度)。

【讨论】:

  • 您的意思是使用u 而不是candidate?在当前代码中,candidate 未初始化。
  • @njuffa 不仅如此,而且candidate 没有声明。我冒昧地修复了它。
【解决方案2】:

fma 以无限精度计算结果,然后应用舍入模式。

如果你的候选项太大,那么无限精确的结果就大于0,既然你是向上取整,就会向上取整。即使它只比零大一点点。为了验证这一点,首先尝试 l = 1 + 2eps,其中 (1 + eps) = sqrt (1 + 2eps + eps^2) 有点太大了;然后将 l 缩小 4 的负幂,使 eps^2 超出非规范化数字的分辨率,并检查它。

【讨论】:

  • 对,当时我想知道 FMA 的准确性,我忘记了处于 RU 模式。处于 RU 模式意味着即使误差可能小于最小的次正规数,它也会做正确的事情。 (另外我仍然认为 (candidate * Candidate - l) 的实际结果不能接近最小的非正规数。在您的说明性公式中,如果 eps^2 远远超出次正规的分辨率,则 1 + eps 只是 1。 )
最近更新 更多