我有一个解方程的数字代码,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。如此处所述,这不仅是我的问题(即,其他人也很生气),仅出现在 x64 上且仅用于x
接近1.0
. 类似的事情也发生在exp
。
解决这个问题对我来说至关重要。有谁知道是否有办法绕过这种缓慢?
编辑:约翰指出这是由于非规范化。那么问题来了,如何解决这个问题?代码是 C++,编译后g++
用于GNU Octave
. 看来,尽管我已设置CXXFLAGS
包含-mtune=native
and -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,这已经足够了。与我发现的相比,开销很小,因此为我解决了这个问题。