Consider the following Fortran program
program test_prg
use iso_fortran_env, only : real64
use mpi_f08
implicit none
real(real64), allocatable :: arr_send(:), arr_recv(:)
integer :: ierr
call MPI_Init(ierr)
allocate(arr_send(3), arr_recv(3))
arr_send = 1
print *, lbound(arr_recv)
call MPI_Gatherv(arr_send, size(arr_send), MPI_DOUBLE_PRECISION, arr_recv, [size(arr_send)], [0], MPI_DOUBLE_PRECISION, 0, MPI_COMM_WORLD, ierr)
print *, lbound(arr_recv)
call MPI_Finalize(ierr)
end program
Execution of this program on 1 processor (compiled with gfortran 9.3.0 and mpich 3.3.2), prints:
1
0
So arr_recv
has changed its lower bound after the call to MPI_Gatherv
. If I use arr_recv(1)
instead of arr_recv
in the call to MPI_Gatherv
, then it doesn't change. If I replace mpi_f08
module with mpi
, then using either arr_recv(1)
or arr_recv
doesn't change the lower bound.
Why is lower bound changing in this program?
At this stage, I believe this is a bug in gfortran
affecting the MPI Fortran 2018 bindings (e.g. use mpi_f08
) and I reported it at https://gcc.gnu.org/pipermail/fortran/2020-September/055068.html.
All gfortran
versions are affected (I tried 9.2.0
, 10.2.0
and the latest master
branch, versions 8
and earlier do not support dimension(..)
.
The reproducer below can be used to evidence the issue
MODULE FOO
INTERFACE
SUBROUTINE dummyc(x0) BIND(C, name="sync")
type(*), dimension(..) :: x0
END SUBROUTINE
END INTERFACE
contains
SUBROUTINE dummy(x0)
type(*), dimension(..) :: x0
call dummyc(x0)
END SUBROUTINE
END MODULE
PROGRAM main
USE FOO
IMPLICIT NONE
integer :: before(2), after(2)
INTEGER, parameter :: n = 1
DOUBLE PRECISION, ALLOCATABLE :: buf(:)
DOUBLE PRECISION :: buf2(n)
ALLOCATE(buf(n))
before(1) = LBOUND(buf,1)
before(2) = UBOUND(buf,1)
CALL dummy (buf)
after(1) = LBOUND(buf,1)
after(2) = UBOUND(buf,1)
if (before(1) .NE. after(1)) stop 1
if (before(2) .NE. after(2)) stop 2
before(1) = LBOUND(buf2,1)
before(2) = UBOUND(buf2,1)
CALL dummy (buf2)
after(1) = LBOUND(buf2,1)
after(2) = LBOUND(buf2,1)
if (before(1) .NE. after(1)) stop 3
if (before(2) .NE. after(2)) stop 4
END PROGRAM
FWIW, Intel ifort
compiler (I tried 18.0.5
) works fine with the reproducer.
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