Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Lbound of an array changes after call to mpi_gatherv when using mpi_f08 module

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?

like image 991
DartLenin Avatar asked Oct 18 '25 15:10

DartLenin


1 Answers

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.

like image 139
Gilles Gouaillardet Avatar answered Oct 22 '25 06:10

Gilles Gouaillardet



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!