gpt4 book ai didi

c++ - 对于非常接近 1 的基数,std::pow() 非常慢

转载 作者:塔克拉玛干 更新时间:2023-11-03 00:08:00 26 4
gpt4 key购买 nike

我有一个求解方程 f(x) = 0 的数字代码,其中我必须提高 x 的幂 p。我用了一堆东西解决了它,但最后我有了牛顿法。解决方案恰好等于 x = 1,因此是我遇到问题的原因。当迭代解接近 1 时,比如 x = 1 + 1e-13,计算 std::pow(x, p)< 所需的时间 以 100 倍的速度快速增长,使我的代码无法使用。

运行这个东西的机器是CentOS上的AMD64(Opteron 6172),命令很简单y = std::pow(x, p);。类似的行为出现在我所有的机器上,都是 x64。如记录here ,这不仅是我的问题(即,其他人也很生气),仅出现在 x64 上并且仅适用于接近 1.0xexp 也发生了类似的事情。

解决这个问题对我来说至关重要。有谁知道是否有任何方法可以解决这种缓慢的问题?

编辑:John 指出这是由于非正规化造成的。那么问题是,如何解决这个问题?代码是 C++,用 g++ 编译,用于 GNU Octave。看来,尽管我已将 CXXFLAGS 设置为包括 -mtune=native-ffast-math,但这并没有帮助,代码只是运行慢慢地。

目前的伪解决方案:对于所有关心这个问题的人来说,下面建议的解决方案对我个人来说并不适用。我确实需要 std::pow() 的通常速度,但又没有 x = 1 的迟缓。我个人的解决方案是使用以下技巧:

inline double mpow(double x, double p) __attribute__ ((const));

inline double mpow(double x, double p)
{
double y(x - 1.0);
return (std::abs(y) > 1e-4) ? (std::pow(x, p)) : (1.0 + p * y * (1.0 + (p - 1.0) * y * (0.5 + (1.0 / 6.0) * (p - 2.0) * y)));
}

边界可以改变,但是对于 -40 < p < 40,误差小于大约 1e-11,这已经足够了。从我发现的情况来看,开销很小,因此为我解决了这个问题。

最佳答案

明显的解决方法是注意在实数中,a ** b == exp(log(a) * b) 并改用该形式。您需要检查它不会对结果的准确性产生不利影响。编辑:正如所讨论的,这也受到几乎同样程度的放缓。

问题不是非正规化,至少不是直接的;尝试计算 exp(-2.4980018054066093e-15) 会遇到同样的减速,并且 -2.4980018054066093e-15 当然不是非正规的。

如果您不关心结果的准确性,那么缩放指数或指数应该会让您脱离慢速区域:

sqrt(pow(a, b * 2))
pow(a * 2, b) / pow(2, b)
...

glibc 维护者已知此错误:http://sourceware.org/bugzilla/show_bug.cgi?id=13932 - 如果您正在寻找解决方案而不是解决方法,您会希望委托(delegate)具有开源经验的 float 学专家。

关于c++ - 对于非常接近 1 的基数,std::pow() 非常慢,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14687665/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com