complex optimisation in Fortran

Whilst Fortran is generally thought of as being easy for a compiler to optimise, that does not prove that all compilers do produce optimal code. One area often thought to be weak is the optimisation of expressions involving complex numbers, because "important" people rarely use them. ("Important" means people paying high licence fees, rather than Theoretical Physicists and applied Mathematicians with discounted academic licences.)

These pages give a snap-shot of the state of some major Fortran compilers on x86_64 Linux at the end of 2018. It should not be used for purchasing decisions if it is not now the end of 2018, or, indeed, probably at all, for very synthetic benchmarks like these are not very representative of performance on real-world code. However, these pages might be of some educational interest. Click on the code snippets below for a link to the corresponding full page.

Optimising conjugation

  do i=1,n
     c(i)=conjg(c(i))
  enddo
  

Optimising scaling complex by real

  real :: a
  do i=1,n
     c(i)=a*c(i)
  enddo
  

Optimising scaling complex by i

  do i=1,n
     c(i)=c(i)*(0d0,1d0)
  enddo
  

These were all timed by using a vector length of 1,000 (assumed to fit in L1 cache), and repeating 10,000,000 times. This should make memory references as cheap as possible, and thus make it easier to see differences in compute effort. Below is an example timing routine for the scaling by real example.

program st
  implicit none
  complex(kind(1d0)), allocatable::c(:)
  real (kind(1d0))::a
  integer :: i,n,rep1
  real t1,t2,t
  n=1000
  allocate(c(n))

  c=1d0
  a=0.99999999d0
  rep1=1e7
  
  call cpu_time(t1)
  do i=1,rep1
     call scale(a,c,n)
  enddo
  call cpu_time(t2)

  write(*,*)'Time=',t2-t1
end