MPI + GCC + GFORTRAN on Windows

This is tested on Windows 7 and and Windows 10 and gcc version 7.1.0 (x86_64-posix-seh-rev2, Built by MinGW-W64 project).

These are instructions to get Mingw + MPI going on windows the easy way. I have tested it for gcc and gfortran.

We need to download 3 items: mingw-w64, MSMPI and MSMPI SDK

  1. Download and Install mingw-w64 somewhere.
  2. Download and install MSMPI and MSMPI SDK from microsoft.

MSMPI provides "mpiexec.exe" MSMPI SDK provides the MPI libraries and header files. We need msmpi.lib and msmpi.dll and the headers files for linking purposes. Upon installation, some environment variables are set-up. Doing "set MSMPI" in a cmd shell will show the directories of interest. For example,

C:\>set MSMPI
MSMPI_BIN=C:\Program Files\Microsoft MPI\Bin\
MSMPI_INC=C:\Program Files (x86)\Microsoft SDKs\MPI\Include\
MSMPI_LIB32=C:\Program Files (x86)\Microsoft SDKs\MPI\Lib\x86\
MSMPI_LIB64=C:\Program Files (x86)\Microsoft SDKs\MPI\Lib\x64\

%MSMPI_INC% is the mpi include directory.

mpiexec is in %MSMPI_BIN%

msmpi.lib is present in %MPI_LIB64%

msmpi.dll is present in %SYSTEMROOT%\System32.

Before going further make sure that mingw and mpiexec are added to path. Easiest way to do this is to open a MINGW shell first and then add mpiexec to the path by doing

C:\> set PATH=%PATH%;%MSMPI_BIN%

Check that mpiexec and gcc both work. Use this shell to carry out the following steps, by navigating into the various directories from here.

  1. Copy msmpi.dll and msmpi.lib to a temporary folder and navigate the mingw cmd window to this folder. Create a static library "libmsmpi.a" using gendef and dlltool.
    
    C:\> mkdir tempdir
    C:\> cd tempdir
    C:\> mkdir include
    C:\tempdir\> copy "%MSMPI_INC%" include
    C:\tempdir\> copy "%MSMPI_LIB64%"\msmpi.lib .
    C:\tempdir\> copy %SYSTEMROOT%\System32\msmpi.dll .
    C:\tempdir\> gendef msmpi.dll
    C:\tempdir\> dlltool -d msmpi.def -l libmsmpi.a -D msmpi.dll
    
  1. libmsmpi.a is the mpi library ready to be used. Put it in a convenient library folder. I suggest C:\lib\mpi\lib
  2. Copy the include folder to another convenient place. I suggest copying to C:\lib\mpi, so that the path to mpi.h is C:\lib\mpi\include\mpi.h. We need to edit some of these files. Leave the original files alone and only edit the copy you make.
  3. Open the file mpi.h and add #include <stdint.h>, just before the line
typedef __int64 MPI_Aint;

At this point MPI C/C++ programs are ready to be compiled. For example, if libmsmpi.a is in C:\lib\mpi\lib and mpi.h is in C:\lib\mpi\include we can compile my_mpi_program.c by:

gcc -o out.exe my_mpi_program.c -IC:\lib\mpi\include -LC:\lib\mpi\lib -lmsmpi

Make sure that mpiexec is in PATH and run the program with

mpiexec -np 4 out.exe

With mingw, gcc has some default search dirs. Additionally, you can set environment variables to point gcc to search in a certain directories for includes or libraries. You can see the default search directories by doing

gcc --print-search-dirs. 

It shows the directories where it looks for <...> includes and "..." includes and libraries by default. If the mpi.h and libmsmpi.a are present in the default search dirs, then compiling MPI C programs is just

gcc -o out.exe my_mpi_program.c -lmsmpi

The mpi header and library are automatically found. We are just letting the linker know that it needs to link against msmpi. More info at http://www.mingw.org/wiki/includepathhowto

Fortran + MPI

Now for Fortran, in the copy of the %MSMPI_INC% you created, do the following:

  1. Rename mpi.f90 to mpi.F90
  2. In both mpi.F90 change find and change
include "mpifptr.h"

to

include "x64/mpifptr.h"
  1. Navigate to this folder in the mingw shell and issue the following command to generate mpi.mod file,
   gfortran -D_WIN64 -D INT_PTR_KIND()=8 -fno-range-check mpi.F90

This should create mpi.mod file without any errors. Now MPI with fortran is ready for primetime. One caveat is we have to do use mpi rather than include "mpif.h" in the program. For example:


program hello
use mpi
implicit none
  integer rank, num_procs, ierror
  
  call MPI_INIT(ierror)
  call MPI_COMM_SIZE(MPI_COMM_WORLD, num_procs, ierror)
  call MPI_COMM_RANK(MPI_COMM_WORLD, rank, ierror)
  print*, 'Process ', rank, ': Hello world'
  call MPI_FINALIZE(ierror)
end

A fortran program using MPI can be compiled with

gfortran -o out.exe my_mpi_program.F90 -IC:\lib\mpi\include -LC:\lib\mpi\lib -lmsmpi

It can be run exactly like the C program.

If libmsmpi.a is found automatically then -LC:\lib\mpi\lib may be left out. The include directory (-I###) is needed because gfortran in mingw does not look anywhere for include files. Also there isn't an environment variable that can be set for include files. So, the include path always has to be explicitly specified for fortran programs with mpi.

The End.

Written with help from:

  1. https://github.com/coderefinery/autocmake/issues/85#issue-102874399
  2. http://www.math.ucla.edu/~wotaoyin/windows_coding.html

PS:

The procedure shown here creates a static library for mpi. We could have used the dynamic libraries as well. Instead of making libmsmpi.a we can use msmpi.dll directly by placing it in the library search path. The commands are same as before. With the dynanmic library GCC works A-okay but gfortran does not. The problem is in the linking step. Compiling to .o with gfortran and linking with gcc with -lgfortran works.