'Order of Operations in Fortran
I'm a new Fortran 90 user and have a relatively simple question. Within a subroutine I'm running the following code:
y = (1-crra)*(f(llc(1) , llc(2) , llc(3) , llc(4) ))**(1/(1-crra))*(1-xin)*(1-yin)*(1-zin)*(1-qin) &
+ (1-crra)*(f(llc(1)+1, llc(2) , llc(3) , llc(4) ))**(1/(1-crra))*xin *(1-yin)*(1-zin)*(1-qin) &
+ (1-crra)*(f(llc(1) , llc(2)+1, llc(3) , llc(4) ))**(1/(1-crra))*(1-xin)*yin *(1-zin)*(1-qin) &
+ (1-crra)*(f(llc(1) , llc(2) , llc(3)+1, llc(4) ))**(1/(1-crra))*(1-xin)*(1-yin)*zin *(1-qin) &
+ (1-crra)*(f(llc(1) , llc(2)+1, llc(3)+1, llc(4) ))**(1/(1-crra))*(1-xin)*yin *zin *(1-qin) &
+ (1-crra)*(f(llc(1)+1, llc(2) , llc(3)+1, llc(4) ))**(1/(1-crra))*xin *(1-yin)*zin *(1-qin) &
+ (1-crra)*(f(llc(1)+1, llc(2)+1, llc(3) , llc(4) ))**(1/(1-crra))*xin *yin *(1-zin)*(1-qin) &
+ (1-crra)*(f(llc(1)+1, llc(2)+1, llc(3)+1, llc(4) ))**(1/(1-crra))*xin *yin *zin *(1-qin) &
+ (1-crra)*(f(llc(1) , llc(2) , llc(3) , llc(4)+1))**(1/(1-crra))*(1-xin)*(1-yin)*(1-zin)*qin &
+ (1-crra)*(f(llc(1)+1, llc(2) , llc(3) , llc(4)+1))**(1/(1-crra))*xin *(1-yin)*(1-zin)*qin &
+ (1-crra)*(f(llc(1) , llc(2)+1, llc(3) , llc(4)+1))**(1/(1-crra))*(1-xin)*yin *(1-zin)*qin &
+ (1-crra)*(f(llc(1) , llc(2) , llc(3)+1, llc(4)+1))**(1/(1-crra))*(1-xin)*(1-yin)*zin *qin &
+ (1-crra)*(f(llc(1) , llc(2)+1, llc(3)+1, llc(4)+1))**(1/(1-crra))*(1-xin)*yin *zin *qin &
+ (1-crra)*(f(llc(1)+1, llc(2) , llc(3)+1, llc(4)+1))**(1/(1-crra))*xin *(1-yin)*zin *qin &
+ (1-crra)*(f(llc(1)+1, llc(2)+1, llc(3) , llc(4)+1))**(1/(1-crra))*xin *yin *(1-zin)*qin &
+ (1-crra)*(f(llc(1)+1, llc(2)+1, llc(3)+1, llc(4)+1))**(1/(1-crra))*xin *yin *zin *qin
When I replace that chunk of code with the following code I get around a 2X speed-up:
y = (((1-crra)*f(llc(1) , llc(2) , llc(3) , llc(4) ))**(1/(1-crra)))*(1-xin)*(1-yin)*(1-zin)*(1-qin) &
+ (((1-crra)*f(llc(1)+1, llc(2) , llc(3) , llc(4) ))**(1/(1-crra)))*xin *(1-yin)*(1-zin)*(1-qin) &
+ (((1-crra)*f(llc(1) , llc(2)+1, llc(3) , llc(4) ))**(1/(1-crra)))*(1-xin)*yin *(1-zin)*(1-qin) &
+ (((1-crra)*f(llc(1) , llc(2) , llc(3)+1, llc(4) ))**(1/(1-crra)))*(1-xin)*(1-yin)*zin *(1-qin) &
+ (((1-crra)*f(llc(1) , llc(2)+1, llc(3)+1, llc(4) ))**(1/(1-crra)))*(1-xin)*yin *zin *(1-qin) &
+ (((1-crra)*f(llc(1)+1, llc(2) , llc(3)+1, llc(4) ))**(1/(1-crra)))*xin *(1-yin)*zin *(1-qin) &
+ (((1-crra)*f(llc(1)+1, llc(2)+1, llc(3) , llc(4) ))**(1/(1-crra)))*xin *yin *(1-zin)*(1-qin) &
+ (((1-crra)*f(llc(1)+1, llc(2)+1, llc(3)+1, llc(4) ))**(1/(1-crra)))*xin *yin *zin *(1-qin) &
+ (((1-crra)*f(llc(1) , llc(2) , llc(3) , llc(4)+1))**(1/(1-crra)))*(1-xin)*(1-yin)*(1-zin)*qin &
+ (((1-crra)*f(llc(1)+1, llc(2) , llc(3) , llc(4)+1))**(1/(1-crra)))*xin *(1-yin)*(1-zin)*qin &
+ (((1-crra)*f(llc(1) , llc(2)+1, llc(3) , llc(4)+1))**(1/(1-crra)))*(1-xin)*yin *(1-zin)*qin &
+ (((1-crra)*f(llc(1) , llc(2) , llc(3)+1, llc(4)+1))**(1/(1-crra)))*(1-xin)*(1-yin)*zin *qin &
+ (((1-crra)*f(llc(1) , llc(2)+1, llc(3)+1, llc(4)+1))**(1/(1-crra)))*(1-xin)*yin *zin *qin &
+ (((1-crra)*f(llc(1)+1, llc(2) , llc(3)+1, llc(4)+1))**(1/(1-crra)))*xin *(1-yin)*zin *qin &
+ (((1-crra)*f(llc(1)+1, llc(2)+1, llc(3) , llc(4)+1))**(1/(1-crra)))*xin *yin *(1-zin)*qin &
+ (((1-crra)*f(llc(1)+1, llc(2)+1, llc(3)+1, llc(4)+1))**(1/(1-crra)))*xin *yin *zin *qin
Why am I getting a speed-up here? Is there a general Fortran lesson here or is this specific to my application?
Solution 1:[1]
I can't comment about speed without knowing more about your variables and the function f. But can I recommend generating y algorithmically rather than with a single huge expression?
Something like
! I'm guessing at the types of these.
integer :: arguments(2,4)
integer :: factors(2,4)
arguments(1,:) = llc
arguments(2,:) = llc+1
factors(1,:) = 1-[xin, yin, zin, quin]
factors(2,:) = [xin, yin, zin, quin]
! Initialise `y` to `0`.
y = 0
! Loop over four indices, one each for x, y, z and q.
do i=1,2
do j=1,2
do k=1,2
do l=1,2
! Calculate the contribution to `y`.
y = y &
+ f(arguments(i,1), arguments(j,2), arguments(k,3), arguments(l,4)) &
** (1/(1-crra)) &
* factors(i,1)*factors(j,2)*factors(k,3)*factors(l,4)
enddo
enddo
enddo
enddo
! Multiply `y` by `(1-crra)`.
y = y*(1-crra)
This might run slower than your code, but with a bit of refactoring it should be possible to make it faster.
The advantages of this kind of approach are that it's much more readable and maintainable.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 |
