Dear everybody,I have a C app calling a piece of fortan code, namely a function called F (say).I have both the C version of F and the Fortran version of F, both calculating in the same way and giving the same results. Lastly I have a testing app, where I call F 100K times and the Fortan F is supplied in a static Release library.When in this app I use the C version of F, the computation takes 2 seconds. However, with the Fortran version of F, it takes around 80 seconds. Is there a way how to solve this? I pretty much need the Fortran version to have the same speed as the C version (the reason is that this F function is fed to a numerical integrator which I only have in Fortran).Any help on this is much appreciated,Daniel

# Performance issues

## Performance issues

For more complete information about compiler optimizations, see our Optimization Notice.

the other issue is 'you have a C app calling' both the F function in C and in Fortran.

So then it becomes 'what are you passing to the F function?' that might be slowing it down when it is in Fortran v in C?

lastly you mention that the F function is fed into a Fortran numerical integrator...shouldn't you do the test of whether the F function when fed to the frotran integrator is faster in C or Fortran?

just a few thoughts to maybe move you forward on the project.

Hello bmcherry,The function is

real*8 function logpweibull(x, kappa, p) COMMON/weibullCommon/ CKAPPA,CP real*8 CKAPPA real*8 CP real*8 kappa real*8 p real*8 x real*8 logpweibulIntegrand CKAPPA = kappa CP = p logpweibull = logpweibulIntegrand(x) end real*8 function logpweibulIntegrand(x) !logpweibulIntegrand real*8 x COMMON/weibullCommon/ CKAPPA,CP real*8 CKAPPA real*8 CP real*8 kappa real*8 p real*8 xi real*8 xitokappa real*8 retval1 real*8 retval2 real*8 retval3 real*8 retval4 real*8 dlgamma kappa = CKAPPA p = CP !kappa = 1.5 !p = 2.0 xi = exp(dlgamma( 1.0 + 1.0/kappa )) xitokappa = xi ** kappa retval1 = log(x) ** p retval2 = kappa * xitokappa retval3 = x ** ( kappa - 1.0 ) retval4= exp( -xitokappa * (x ** kappa) ) logpweibulIntegrand = retval1*retval2*retval3*retval4 endand in C it is

double Logp_Weibull( double x, void * params ) { double kappa = ((double*)params)[0]; double p = ((double*)params)[1]; double arg = 1.0 + 1.0/kappa; double xi = GAMMA( & arg); double dXiToKappa = pow(xi, kappa); double RetVal1 = pow( log(x), p ); double RetVal2 = kappa * dXiToKappa; double RetVal3 = pow( x, kappa - 1 ); double RetVal4 = exp( -dXiToKappa * pow(x, kappa) ); return RetVal1 * RetVal2 * RetVal3 * RetVal4; }It is pretty straight forward, so I think no coding issues are doing this. Also, when creating a Fortran application that calls thislogpweibull function 1M times, it runs 9 seconds. The same thing in C, i.e. a main() calling 1M times the CLogp_Weibull function takes 21 seconds. So...Fortran per se is faster. Now my original app slowing down with using using a Fortran library is weird. I was thinking along the lines of "changing context" when going from C code to Fortran, but I dont know whether there is something like that.The reason Im not feeding the integral as a C function is that it needs to be parametrized by kappa, p yet can take only one argument (x). Hence, I need to do it like this.Thanks again,Daniel

Surely you could replace xi**kappa * x**kappa by (xi*x)**kappa in case one of the compilers doesn't perform such an algebraic optimization.

If you expect p to take an integral value, pow() is expected to perform appropriate optimization internally, while Fortran expects you to write that explicitly. It's even possible that pow() may perform optimizations involving sqrt(), in case your comments about expected values are significant.

(Assuming that GAMMA(&arg) in the C code is equivalent to exp(dlgamma(1.0+1.0/kappa) in the fortran)

Which C compiler? What command line options are in use for both the C and fortran compilers, in all the cases that you are comparing? Are you using any optimisation? Any inter-procedural optimisation? Any inter-procedural optimisation that works across languages?

Why are you putting kappa and p into common and not passing them as arguments? That means that the logpweibull fortran function has side effects. The C variant does not have these side effects - so the two variants aren't equivalent, particularly from the point of view of a code optimiser.

If it is a compute time problem, I'd be looking to minimise the use of " ** double ", as this is much less efficient than " ** integer "

There was a time when a**b was replaced by exp(b*log(a))

It's been a while but I think that retval4 = kappa * exp(x)- exp(xitokappa)

or replace x ** kappa with retval3 * x, giving retval4 = exp (-xitokappa*retval3*x)

Also, if log(x)**p = exp(p*log(log(x))) what does this mean ??

Some potential changes there.

Alternatively it may be in the C > F and F > C interface.

C++>>doublearg=1.0+1.0/kappa;

IVF>>xi=exp(dlgamma(1.0+1.0/kappa))

In C++ 1.0 is a double precision literal

In IVF 1.0 is a single precision literal (when using default options)

Try changing your floating point literals to double precision.

Jim Dempsey

www.quickthreadprogramming.com

integer, parameter :: dp = selected real kind(12)

real(dp) :: kappa

xi = exp(dlgamma(1_dp + 1_dp/kappa))

but in this case the code generated should be identical.

Alert! 1_dp is an INTEGER literal.