为什么我的程序的这个简单部分使我打了两个多小时

Why does this simple part of my program makes me struck for more than two hours?

本文关键字:小时 两个 程序 我的 简单部 为什么      更新时间:2023-10-16

我粘贴了下面程序的一部分,为什么要花大量时间进行执行?

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) ;
                }
        }
    }

好吧,如果N为1000,它将执行pow 200万次。在这种情况下,pow执行log,然后进行乘法,然后进行exp。这是沉重的代码。

我只想指出,如果您想知道,编译器优化对此代码没有帮助,因为该程序计数器几乎将其所有时间花在logexp中。

另外,正如@Amon指出的那样,您可以摆脱一个pow呼叫,给出两个速度。

在其上,您将生成2 n ** 2调用pow()。POW()很昂贵,涉及每个呼叫的log()和exp()的呼叫。对于n = 1000,也就是说,正如另一个人所观察到的那样,log()和exp()的呼叫。

log()和exp()本身很昂贵,是浮点功率系列扩展。

您的编译器可能知道数字。正方形。这将使您的第二个示例中的运行时间大大减少。

dijkstra曾经观察到(在一个研究生的招聘演讲中),练习的目的是"不要弄乱它"。观察POW(x,2)== x * x and pow(x,1.5)== x * sqrt(x),您可以通过定义两个(inline)函数并重写两个(inline)函数来摆脱很多先验的数字呼叫关键线为:

    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));