Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a better way to optimize the lennard jones potential function?

Tags:

performance

c

In actual fact, its the derivative of the Lennard Jones potential. The reason for is that I am writing a Molecular Dynamics program and at least 80% of the time is spent in the following function, even with the most aggressive compiler options (gcc ** -O3).

double ljd(double r) /* Derivative of Lennard Jones Potential for Argon with 
                        respect to distance (r) */ 
{  
    double temp;  
    temp = Si/r;  
    temp = temp*temp;
    temp = temp*temp*temp;  
    return ( (24*Ep/r)*(temp-(2 * pow(temp,2))) );  
}  

This code is from a file "functs.h", which I import into my main file. I thought that using temporary variables in this way would make the function faster, but I am worried that creating them is too wasteful. Should I use static? Also the code is written in parallel using openmp, so I can't really declare temp as a global variable?

The variables Ep and Si are defined (using #define). I have only been using C for about 1 month. I tried to look at the assembler code generated by gcc, but I was completely lost.\

like image 310
sn6uv Avatar asked Dec 10 '22 11:12

sn6uv


2 Answers

I would get rid of the call to pow() for a start:

double ljd(double r) /* Derivative of Lennard Jones Potential for Argon with 
                        respect to distance (r) */ 
{  
    double temp;  
    temp = Si / r;  
    temp = temp * temp;
    temp = temp * temp * temp;  
    return ( (24.0 * Ep / r) * (temp - (2.0 * temp * temp)) );  
}  
like image 77
Paul R Avatar answered Jan 18 '23 09:01

Paul R


On my architecture (intel Centrino Duo, MinGW-gcc 4.5.2 on Windows XP), non-optimized code using pow()

static inline double ljd(double r)
{
    return 24 * Ep / Si * (pow(Si / r, 7) - 2 * pow(Si / r, 13));
}

actually outperforms your version if -ffast-math is provided.

The generated assembly (using some arbitrary values for Ep and Si) looks like this:

fldl    LC0
fdivl   8(%ebp)
fld     %st(0)
fmul    %st(1), %st
fmul    %st, %st(1)
fld     %st(0)
fmul    %st(1), %st
fmul    %st(2), %st
fxch    %st(1)
fmul    %st(2), %st
fmul    %st(0), %st
fmulp   %st, %st(2)
fxch    %st(1)
fadd    %st(0), %st
fsubrp  %st, %st(1)
fmull   LC1
like image 41
Christoph Avatar answered Jan 18 '23 09:01

Christoph