Parallel Fortran Without Rewriting Your Math in MPI
Fortran coarrays let numerical code run across images using familiar array syntax. Learn when to use them and where MPI still wins.
21 Jun 2026, 04:20 UTC

The problem: parallelism should not hide the math
You inherit a Fortran finite-difference kernel that runs for hours on one core. The obvious next step is to spread the grid across multiple program instances, but rewriting every loop as MPI send and receive calls buries the array mathematics under communication boilerplate. You want the parallel version to look as close as possible to the serial code.
What coarrays change
Fortran coarrays, standardized in Fortran 2008 and extended in Fortran 2018, implement a Partitioned Global Address Space model directly in the language. A Partitioned Global Address Space lets each running copy, called an image, read and write variables on other images using familiar syntax. Declaring a variable with codimension[*] gives every image its own storage slot. Remote access uses square brackets, such as source[p], while ordinary parentheses keep access local.
The two intrinsics you check first are num_images(), which returns the total image count, and this_image(), which returns the current image's number. Together they let you split work by image without explicit rank management.
Synchronization and memory order
Coarrays do not assume that images execute in lockstep. The statement sync all pauses execution until every image reaches it, which makes writes visible across images. sync images targets a specific subset, and sync memory orders memory operations on a single image. For finer control, critical blocks and lock variables serialize access to shared data. A missing or unbalanced sync all is a common source of deadlocks, especially under batch schedulers where one image may lag behind the others.
Worked example: parallel reduction
This example splits a summation across images. Each image computes a partial sum over its slice, stores it in a coarray, and image one collects the results. The code assumes the problem size divides evenly by the image count; production code should handle the remainder.
program slice_reduction
implicit none
integer, parameter :: n = 1_000_000
real(8), codimension[*] :: partial
real(8) :: my_value, grand_total
integer :: me, images, i, lo, hi
images = num_images()
me = this_image()
lo = (me - 1) * (n / images) + 1
hi = me * (n / images)
my_value = 0.0_8
do i = lo, hi
my_value = my_value + real(i, 8)
end do
partial = my_value
sync all
if (me == 1) then
grand_total = 0.0_8
do i = 1, images
grand_total = grand_total + partial[i]
end do
print *, 'Parallel sum:', grand_total
print *, 'Serial check :', real(n, 8) * (real(n, 8) + 1.0_8) / 2.0_8
end if
sync all
end program slice_reduction
Compile from a normal user account; no elevated privileges are required:
gfortran -fcoarray=lib -o slice_reduction slice_reduction.f90
Run with an MPI launcher, because many coarray runtimes use MPI underneath:
mpiexec -np 4 ./slice_reduction
If your vendor supplies a different launcher, such as cafrun, substitute it for mpiexec. The placeholder -np 4 means four images; adjust to your allocation.
How to verify the result
- Run with -np 1 and confirm the parallel sum matches the serial check.
- Run with -np 4 and confirm num_images() returns four and this_image() spans one through four.
- Compare the printed parallel sum against the serial check. They should match to floating-point rounding.
- If the program hangs, check that every image reaches the same sync all statements in the same order.
Trade-offs versus MPI
Coarrays are not a universal MPI replacement. The table below shows where each model fits.
| Concern | Coarrays | MPI |
|---|---|---|
| Readability for regular arrays | Native codimension[*] and [p] syntax | Explicit send, receive, or one-sided calls |
| Communication topologies | Mostly single program, multiple data images | Cartesian graphs, non-blocking, persistent requests |
| Vendor maturity | Improving; Fortran 2018 features uneven | Broad and well tuned |
| Threads inside an image | Not automatic; combine with OpenMP carefully | Same caveat; MPI plus OpenMP is common |
Limitations
- Coarrays express parallelism between images, not threads within an image. Adding OpenMP requires care to avoid oversubscribing cores.
- Fortran 2018 collectives such as co_sum and teams have uneven compiler support. Check your compiler's standards table before relying on them.
- Mismatched sync statements cause deadlocks that are harder to diagnose than a failed MPI send.
Actionable closing
Start with a self-contained numerical kernel where communication is regular and the image count is fixed. Compile with gfortran -fcoarray=lib or your vendor's equivalent, run under mpiexec or cafrun, and verify against a known serial result on one image before scaling. Keep MPI for legacy integration or complex hybrid workflows; choose coarrays when you want the parallel code to look like the mathematics.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.