问题描述
考虑以下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.0
,10.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
)在复制器上正常工作。