Performance Optimization
33.1 Compiler flags
use the host CPU's instruction set (AVX2/AVX-512) link-time / interprocedural optimization -Ofast / -ffast-math -fp-model fast relaxed IEEE (careful!)
33.2 Memory layout & loop order
! GOOD: inner loop over the first index (contiguous in column-major order)
do j = 1, n
do i = 1, n
c(i, j) = a(i, j) + b(i, j)
end do
end do
! BAD: strided access → cache misses (can be 5–10× slower for large arrays)
do i = 1, n
do j = 1, n
c(i, j) = a(i, j) + b(i, j)
end do
end do33.3 Optimization checklist
Profile first (gprof -pg, perf, Intel VTune, AMD uProf, Linaro MAP/Forge).
Choose good algorithms and use optimized libraries (BLAS dgemm vs naive loops: 10–100×).
Access memory contiguously; use structure-of-arrays for vectorization.
Avoid temporary arrays: watch -Warray-temporaries (gfortran); non-contiguous sections passed to explicit-shape dummies create copies.
Use contiguous attribute on assumed-shape/pointer dummies when appropriate.
Hoist invariants out of loops; avoid function calls with side effects in inner loops (or make them pure/inlined).
Allocate once, reuse buffers; avoid allocation in hot loops.
Prefer allocatable over pointer (no aliasing → better optimization).
Use do concurrent / OpenMP simd for vectorization hints.
Cache blocking (tiling) for large matrix operations.
Mixed precision where accuracy allows.
Parallelize: OpenMP for cores, MPI for nodes, GPUs for massive throughput.
33.4 Timing code
integer(int64) :: t0, t1, rate
real :: c0, c1
call system_clock(t0, rate)
call cpu_time(c0)
call heavy_work()
call cpu_time(c1)
call system_clock(t1)
print '(a, f8.3, a, f8.3, a)', "wall: ", real(t1 - t0) / rate, " s, cpu: ", c1 - c0, " s"