我正在编写一个解决平面受限三体问题的程序。它的方程式如下。此函数计算位置和速度的导数,并将它们写入数组。
valarray<double> force(double t, valarray<double> r)
{
valarray<double> f(dim);
valarray<double>r0(r-rb0);
valarray<double>r1(r-rb1);
f[0]= 2 * r[1] + r[2] - (1 - mu)*r0[2]/norm3(r0) - mu*r1[2]/norm3(r1);
f[1]= - 2 * r[0] + r[3] - mu*r0[3]/norm3(r0) - mu*r1[3]/norm3(r1);
f[2] = r[0];
f[3] = r[1];
return f;
}
double norm3(valarray<double> x)
{
return pow(x[2]*x[2]+x[3]*x[3],1.5);
}
所以我必须计算位置矢量的平方,然后将其提高到3/2的幂。我认为这些操作占用了很大一部分计算时间。
现在我使用math.h的pow函数。还有另一种更快的算法来计算这种功率吗?我尝试使用fast inverse square root(并稍后将其立方体化),但它为我的目的提供了太不精确的值并且工作时间更长(可能是因为立方体)。
谢谢!
答案 0 :(得分:5)
一个简单的方法可能是尝试x * sqrt(x),但要确定它的基准。
double norm3(valarray<double> x)
{
double result=x[2]*x[2]+x[3]*x[3];
result=result * sqrt(result);
return result;
}
答案 1 :(得分:1)
家庭15小时AMD64处理器中的FSQRT
需要52个周期。 SSE2变体的标量值为29,打包操作为38。 sqrt()
的C版本可能是一些额外的指令,但我怀疑它还有更多。
如果你想要相对精确的结果,我怀疑从其他一些操作得到的好多了。最有可能的是,任何涉及pow()
,exp()
和log()
等的精确度都会提高。
然而,在互联网上询问并没有超过你自己的基准。如果这是您的代码的关键部分,请尝试一些不同的变体,看看你得到了什么。