Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Fortran error: type mismatch between two unrelated subroutine calls

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.

like image 733
bob.sacamento Avatar asked Sep 14 '20 21:09

bob.sacamento


Video Answer


2 Answers

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.

like image 115
John Bollinger Avatar answered Oct 17 '22 03:10

John Bollinger


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.

like image 22
Roux Avatar answered Oct 17 '22 01:10

Roux