I'm studying around the impact of unrolling and optimisation flags on Fortran code. I come up with the following, very trivial, case:
program do_order
implicit none
integer :: j, s, n, nLoops
integer, dimension(4) :: Iv
real*8, dimension(16, 4) :: tmp, Ov
real :: start, finish
nLoops = 1000000
!! Initialize the values of Input vector;
do n = 1,4
Iv(n) = n**2
end do
!! Explicit Do-loop + implicit Do-loop working across columns (to be Fortran efficient)
call cpu_time(start)
do n = 1, nLoops
tmp = 0.d0
Ov = 0.d0
do j = 1,4
tmp(1:Iv(j),j) = Ov(1:Iv(j),j) - 10.0d0
end do
end do
call cpu_time(finish)
print '("Loop-1 Time = ",f6.3," seconds.")',finish-start
tmp = 0.d0
Ov = 0.d0
!! Un-rolled loop + implicit Do-loop
call cpu_time(start)
do n = 1, nLoops
tmp = 0.d0
Ov = 0.d0
tmp(1:Iv(1),1) = Ov(1:Iv(1),1) - 10.0d0
tmp(1:Iv(2),2) = Ov(1:Iv(2),2) - 10.0d0
tmp(1:Iv(3),3) = Ov(1:Iv(3),3) - 10.0d0
tmp(1:Iv(4),4) = Ov(1:Iv(4),4) - 10.0d0
end do
call cpu_time(finish)
print '("Loop-2 Time = ",f6.3," seconds.")',finish-start
end program
Compiled with: -O3 -mprefer-avx128 flags, gives me the following timing:
Loop-1 Time = 4.487 seconds. Loop-2 Time = 3.657 seconds.
I've used Gfort: GNU Fortran (Ubuntu 9.3.0-17ubuntu1~20.04) 9.3.0. I have access also to
Ifort 19.1.3.304. The same test with Ifort -O3 gives me:
Loop-1 Time = 0.939 seconds. Loop-2 Time = 0.873 seconds.
My questions:
- Why the huge gap in performance between Gfort and Ifort?
- did I unrolled the second loop correctly?
- Are there other optimization flags to speedup the code even more (i.e. Loop unrolling & optimization, Decreasing the fortran run time by extra optimization flags)?
- Are there other strategies to speedup the code even more (without moving to multithreading, for now)?