This Fortran MPI program is, to my mind, completely straightforward:
program what
use mpi
integer(4), parameter :: ksp = 4
integer(4), parameter :: kdp = 8
integer(ksp) :: nreadslb
integer(ksp), ALLOCATABLE :: all_nreadslb(:)
real(kdp) :: compute_time
real(kdp), ALLOCATABLE :: all_compute_times(:)
integer(ksp) :: myrank
integer :: ierr
call mpi_init(ierr)
allocate(all_nreadslb(10), all_compute_times(10))
CALL MPI_GATHER(compute_time, 1, &
MPI_DOUBLE_PRECISION, all_compute_times, 1, &
MPI_DOUBLE_PRECISION, 0, MPI_COMM_WORLD, ierr)
CALL MPI_GATHER(nreadslb, 1, MPI_INTEGER4, &
all_nreadslb, 1, MPI_INTEGER4, 0, &
MPI_COMM_WORLD, ierr)
call mpi_finalize(ierr)
end program
But it fails to compile on a Cray platform under GNU. The error returned is:
23 | CALL MPI_GATHER(compute_time, 1, &
| 2
......
26 | CALL MPI_GATHER(nreadslb, 1, MPI_INTEGER4, &
| 1
Error: Type mismatch between actual argument at (1) and actual argument at (2) (INTEGER(4)/REAL(8)).
The real kicker is that if I comment out the first MPI_GATHER, the second one compiles just fine, and if I comment out the second MPI_GATHER, the first one compiles just fine. There is something about having the both of them in the code that the GNU compiler does not like. Just for grins, I put a debug statement in between them; got the same error. The code compiles just fine under Cray or Intel Fortran.
Any ideas what the problem could be?
EDIT: I am using the Cray environment PrgEnv-gnu/6.0.9 which uses gfortran from gcc 10.1.0 and Cray MPICH 7.7.16. I am compililng with the Cray "ftn" command, no flags, just ftn what.f90
. Also found out that the problem is with gcc 10.1.0; code compiles just fine under 9.3.0. So that solves the immediate problem. But if anyone knows what to do under 10.1.0 (since 9.3.0 won't last forever) would love to hear it! Thanks.
Without going into detail on whether or why the example program should be accepted, as this depends on Fortran language version and on details of the MPI module in use, GCC 10 brings stricter type checking for Fortran procedure arguments. You should be able to convert these particular errors into warnings by adding the -fallow-argument-mismatch
option to your compilation command line. This has been effective for other projects, such as NetCDF.
UPD: Looks like the recipe, while working in GCC10 in Ubuntu 20.04, causes a memory corruption, at least with GNU Fortran (GCC) 8.3.0 20190222 (Cray Inc.) and cray-mpich/7.7.9. Use with extreme care!
Compiling of your code against openMPI goes with no issues. The issue is in MPICH bindings, and there are still debates whether the it is gcc or MPICH to be fixed:).
I do not like the idea of suppressing any warnings, as they might be of help sometimes. Another way would be to wrap C_LOC() around the arguments in question (that is the best match to void* in the actual C calls behind). This wrapper should do no harm regardless the MPI library or a compiler version.
You would need to add
use, intrinsic :: ISO_C_BINDING, only: c_loc
in the preamble of the program, declare the first arguments of the calls for MPI_GATHER as TARGET (pointers would do as well)
integer(ksp), TARGET :: nreadslb
integer(ksp), ALLOCATABLE, TARGET :: all_nreadslb(:)
real(kdp), TARGET :: compute_time
real(kdp), ALLOCATABLE, TARGET :: all_compute_times(:)
and wrap the arguments with C_LOC
CALL MPI_GATHER(C_LOC(compute_time), 1, &
MPI_DOUBLE_PRECISION, C_LOC(all_compute_times), 1, &
MPI_DOUBLE_PRECISION, 0, MPI_COMM_WORLD, ierr)
CALL MPI_GATHER(C_LOC(nreadslb), 1, MPI_INTEGER4, &
C_LOC(all_nreadslb), 1, MPI_INTEGER4, 0, &
MPI_COMM_WORLD, ierr)
Then compilation goes without errors.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With