我在下面粘贴了我的程序的一部分,为什么需要花费大量的时间来执行?
for(i=0;i<N;i++)
{
for(j=0;j<N;j++)
{
if(j<i) {
pot[i]+=-(x[i]-x[j])*1./pow((pow(x[i]-x[j],2.)+ blah blah,1.5);
}
if(j>i) {
pot[i]+=(x[i]-x[j])*1./pow((pow(x[i]-x[j],2.)+blah blah,1.5);
}
}
}
运行差不多需要两个小时,如果我将1.5作为1.4,那么一切都会好的。
下面的那个非常精细
for(i=0;i<N;i++)
{
pot[i]=0.0;
for(j=0;j<N;j++)
{
if(j<i)
{
pot[i]+=-1.*(x[i]-x[j])/pow(pow(x[i]-x[j],3.)+blah blah,1.);
}
if(j>i)
{
pot[i]+=1.*(x[i]-x[j])/pow(pow(x[i]-x[j],1.)+blah blah,3.);
}
}
}
/ *我非常需要我的程序中的前一个,而不是后来的一个* /
以上是该块的一部分
for(i=0;i<N;i++)
{
for(j=0;j<N;j++)
{
if(j<i)
{
pot[i]+=-(x[i]-x[j])*1./pow(fabs(pow(x[i]-x[j],2.)+ g*g*pow(x[i+N]-x[j+N],2.)+ h*h*pow(x[i+2*N]-x[j+2*N],2.)),1.5) ;
}
if(j>i)
{
pot[i]+=(x[i]-x[j])*1./pow(fabs(pow(x[i]-x[j],2.) + g*g*pow(x[i+N]-x[j+N],2.) + h*h*pow(x[i+2*N]-x[j+2*N],2.)),1.5) ;
}
}
}
答案 0 :(得分:5)
好吧,如果N
为1000,它将执行pow
两百万次。在这种情况下,pow
会执行log
,然后是乘法,然后是exp
。这是沉重的代码。
我只想指出,如果您想知道,编译器优化对此代码没有帮助,因为程序计数器几乎所有时间都花在log
和exp
上。
另外,正如@amon指出的那样,你可以摆脱一个pow
电话,给出两倍的加速。
答案 1 :(得分:3)
按照目前的情况,你将对pow()产生2个N ** 2个调用。 pow()很昂贵,每次调用pow()都会调用log()和exp()。对于N = 1000,也就是说,正如另一个人观察到的那样,每次调用200万次log()和exp()。
log()和exp()本身很昂贵,是浮点幂级数扩展。
你的编译器知道像2.和3这样的数字实际上是小整数,并且知道如何将pow(x,N)(其中N是一个小整数)减少到适当的乘法系列,这是可能的。广场。这样可以大大减少第二个例子的运行时间。
Dijkstra曾经观察过(在一个研究生招募演讲中),演习的目标是“不要弄乱它”。观察pow(x,2)== x * x和pow(x,1.5)== x * sqrt(x),你可以通过定义两个(内联)函数并重写来摆脱大量的超越数字训练调用关键线: pot[i]+=(x[i]-x[j])*1./xsqrtx(square(x[i]-x[j])+blahblah);
另外,如果您实际上是在C / C ++中这样做,那么缓存点差可能是值得的。
delta = x(i]-x[j];
pot[i]+=(delta)*1./xsqrtx(square(delta)+blahblah);
不允许C / C ++假设x在你不看时没有改变,并且进行这种特殊的常见子表达式优化。 (FORTRAN是,并且确实。)
最后,你知道你可以划分浮点数吗?
delta = x(i]-x[j];
pot[i]+=(delta)/(xsqrtx(square(delta)+blahblah));