Skip to content

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.

See Also