使用mpi_f08模块

问题描述

考虑以下Fortran程序

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_COMM_WORLD,ierr)
  print *,lbound(arr_recv)
  call MPI_Finalize(ierr)
end program

在1个处理器上执行该程序(与gfortran 9.3.0和mpich 3.3.2编译),打印:

       1
       0

因此,arr_recv已在调用MPI_Gatherv之后更改了其下限。如果在对arr_recv(1)调用中使用arr_recv而不是MPI_Gatherv,则它不会改变。如果我将mpi_f08模块替换为mpi,则使用arr_recv(1)arr_recv都不会更改下限。

为什么该程序的下限会发生变化?

解决方法

在此阶段,我认为这是gfortran中的一个错误,会影响MPI Fortran 2018绑定(例如use mpi_f08),我在https://gcc.gnu.org/pipermail/fortran/2020-September/055068.html上报告了该错误。 所有gfortran版本都受到影响(我尝试过9.2.010.2.0和最新的master分支,版本8和更早的版本不支持dimension(..)

下面的复制者可以用来证明问题所在

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,英特尔ifort编译器(我尝试过18.0.5)在复制器上正常工作。