【发布时间】:2013-01-19 04:58:19
【问题描述】:
我有一个解方程 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.0 的 x 上。 exp 也发生了类似的事情。
解决这个问题对我来说至关重要。有谁知道是否有办法解决这种缓慢的问题?
编辑: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
【问题讨论】:
-
这可能与subnormal numbers 的一般性能问题有关。浮点值非常接近 0 的计算可能比正常情况慢 100 倍。见stackoverflow.com/questions/9314534/…。
-
好点。关于如何解决这个问题的任何建议?如果数字足够接近,则将数字固定为 1?
-
@JohnKugelman:如果您阅读链接,这是因为 glibc 在给定某些输入值时使用了一个慢得多的函数(名为
__slowpow)。 -
@fledglingCxxuser
-ffast-math违反了 IEEE754 合规性。这是真的坏还是好的取决于你的用例,但如果我是你,我会在启用该标志之前做一些进一步的研究以了解它在做什么。
标签: c++ performance glibc pow