Fortran¶
Fortran (formerly FORTRAN) is a high-performance programming language that has been the backbone of scientific computing for decades.
Compiler Support¶
Multiple Fortran compilers are available on NERSC systems.
| Vendor | PrgEnv | Base Compiler | Wrapper |
|---|---|---|---|
| LLVM | PrgEnv-llvm | flang | mpif90 |
| GNU | PrgEnv-gnu | gfortran | ftn |
| NVIDIA | PrgEnv-nvidia | nvfortran | ftn |
| Cray | PrgEnv-cray | crayftn | ftn |
| Intel | PrgEnv-intel | ifx | ftn |
| AOCC | PrgEnv-aocc | flang | ftn |
For detailed information about each compiler, see the base compilers and compiler wrappers documentation.
Using Fortran at NERSC¶
The recommended way to compile Fortran code on NERSC systems is to use the appropriate compiler wrapper for the toolchain (ftn or mpif90).
Parellel (shared memory, CPU, GPU)¶
A variety of APIs which support shared memory style programming of CPUs and GPUs are available in Fortran:
Parallel (distributed)¶
MPI¶
There are official language bindings for MPI in Fortran. Generally, it is recommended to use mpi_f08 when possible for the safest, most modern version of that API.
Use of mpi_f08 with NVIDIA compilers
use mpi_f08 is not currently supported by the combination of MPICH derivatives (i.e. cray-mpich) and nvfortran.
Coarray¶
Fortran has a native support for a PGAS parallel programming model via coarrays. The put/get semantics and integration with the language enable compact and expressive high-performance code.
To illustrate the difference from MPI consider a 1d ring exchange:
! MPI: Ring exchange
integer :: my_val, recv_val, left, right, req(2), stat(MPI_STATUS_SIZE,2)
call MPI_Comm_rank(MPI_COMM_WORLD, rank, ierr)
call MPI_Comm_size(MPI_COMM_WORLD, nprocs, ierr)
left = mod(rank - 1 + nprocs, nprocs)
right = mod(rank + 1, nprocs)
my_val = rank * 10
call MPI_Isend(my_val, 1, MPI_INTEGER, right, 0, MPI_COMM_WORLD, req(1), ierr)
call MPI_Irecv(recv_val, 1, MPI_INTEGER, left, 0, MPI_COMM_WORLD, req(2), ierr)
call MPI_Waitall(2, req, stat, ierr)
A similar motif with coarrays:
! Coarray: Ring exchange
integer :: val[*], left
val = this_image() * 10
sync all
left = merge(num_images(), this_image()-1, this_image()==1)
val = val[left] ! read from left neighbor (wraps around)
Corarry support varies by system and compiler. On Perlmutter the most mature implementation is available from PrgEnv-cray.