调用参数为指针别名的子例程
Invoking a subroutine where the argument is pointer alias
我不确定这是否符合 Fortran 标准。我有一个通过重载调用的子程序。这里的要点是有时我可能会调用子例程,其中我有指向 real
的指针别名。
请查看此完整代码。
module mpi_intf_exam
use mpi
interface GLB_SUM
module procedure GLB_SUM_INT
module procedure GLB_SUM_FLT
module procedure GLB_SUM_FLT_INPLACE
end interface
integer :: mpierr
contains
subroutine GLB_SUM_INT(buf, buf_out, n)
implicit none
integer, intent(in) :: n
integer, intent(in) :: buf(n)
integer, intent(out) :: buf_out(n)
call mpi_allreduce( buf, buf_out, n, MPI_INTEGER, MPI_SUM, MPI_COMM_WORLD, mpierr)
end subroutine
subroutine GLB_SUM_FLT(buf, buf_out, n)
implicit none
integer, intent(in) :: n
real, intent(in) :: buf(n)
real, intent(out) :: buf_out(n)
call mpi_allreduce( buf, buf_out, n, MPI_REAL, MPI_SUM, MPI_COMM_WORLD, mpierr)
end subroutine
subroutine GLB_SUM_FLT_INPLACE(buf, n)
implicit none
integer, intent(in) :: n
real, intent(inout) :: buf(n)
call mpi_allreduce( MPI_IN_PLACE, buf, n, MPI_REAL, MPI_SUM, MPI_COMM_WORLD, mpierr)
end subroutine
end module
program test_gather
use mpi_intf_exam
implicit none
integer :: rank, ierr, nranks, n, i
real, allocatable, target :: bufs(:), bufr(:)
real, pointer :: ptr(:)
call mpi_init(ierr)
call MPI_COMM_RANK(MPI_COMM_WORLD, rank, ierr)
call MPI_COMM_SIZE(MPI_COMM_WORLD, nranks, ierr)
n = 10
allocate(bufs(n))
ptr => bufs
call random_number(ptr)
ptr = ptr*(rank+1)
print*, sum(bufs), rank, "BEF"
call GLB_SUM(ptr,n) !
print*, sum(bufs), rank
end program
我的调用call GLB_SUM(ptr,n)
是为了调用例程GLB_SUM_FLT_INPLACE
。但是正如您所见,这个子例程有真正的伪参数,而我用 real pointer
调用它。
对于此特定示例,它适用于 IFORT V19.0.5。但它有效吗?我找不到关于这种调用的标准。
将指针传递给非指针伪参数没有问题。 Fortran 不需要任何您可能从其他编程语言中了解到的取消引用。子例程只接收作为指针目标的数组。没关系。
这样使用指针是合法的。
当在过程引用中使用指针对应于非指针伪参数时,指针的目标被视为与实际参数相关联。指针本身必须是指针关联的。对于 Fortran 2018,您可以看到 15.5.2.3.
在问题的情况下,通用 GLB_SUM
的每个特定子例程都没有指针参数。
我不确定这是否符合 Fortran 标准。我有一个通过重载调用的子程序。这里的要点是有时我可能会调用子例程,其中我有指向 real
的指针别名。
请查看此完整代码。
module mpi_intf_exam
use mpi
interface GLB_SUM
module procedure GLB_SUM_INT
module procedure GLB_SUM_FLT
module procedure GLB_SUM_FLT_INPLACE
end interface
integer :: mpierr
contains
subroutine GLB_SUM_INT(buf, buf_out, n)
implicit none
integer, intent(in) :: n
integer, intent(in) :: buf(n)
integer, intent(out) :: buf_out(n)
call mpi_allreduce( buf, buf_out, n, MPI_INTEGER, MPI_SUM, MPI_COMM_WORLD, mpierr)
end subroutine
subroutine GLB_SUM_FLT(buf, buf_out, n)
implicit none
integer, intent(in) :: n
real, intent(in) :: buf(n)
real, intent(out) :: buf_out(n)
call mpi_allreduce( buf, buf_out, n, MPI_REAL, MPI_SUM, MPI_COMM_WORLD, mpierr)
end subroutine
subroutine GLB_SUM_FLT_INPLACE(buf, n)
implicit none
integer, intent(in) :: n
real, intent(inout) :: buf(n)
call mpi_allreduce( MPI_IN_PLACE, buf, n, MPI_REAL, MPI_SUM, MPI_COMM_WORLD, mpierr)
end subroutine
end module
program test_gather
use mpi_intf_exam
implicit none
integer :: rank, ierr, nranks, n, i
real, allocatable, target :: bufs(:), bufr(:)
real, pointer :: ptr(:)
call mpi_init(ierr)
call MPI_COMM_RANK(MPI_COMM_WORLD, rank, ierr)
call MPI_COMM_SIZE(MPI_COMM_WORLD, nranks, ierr)
n = 10
allocate(bufs(n))
ptr => bufs
call random_number(ptr)
ptr = ptr*(rank+1)
print*, sum(bufs), rank, "BEF"
call GLB_SUM(ptr,n) !
print*, sum(bufs), rank
end program
我的调用call GLB_SUM(ptr,n)
是为了调用例程GLB_SUM_FLT_INPLACE
。但是正如您所见,这个子例程有真正的伪参数,而我用 real pointer
调用它。
对于此特定示例,它适用于 IFORT V19.0.5。但它有效吗?我找不到关于这种调用的标准。
将指针传递给非指针伪参数没有问题。 Fortran 不需要任何您可能从其他编程语言中了解到的取消引用。子例程只接收作为指针目标的数组。没关系。
这样使用指针是合法的。
当在过程引用中使用指针对应于非指针伪参数时,指针的目标被视为与实际参数相关联。指针本身必须是指针关联的。对于 Fortran 2018,您可以看到 15.5.2.3.
在问题的情况下,通用 GLB_SUM
的每个特定子例程都没有指针参数。