关于Fortran中MPI包装子例程从假定大小参数改为假定形状参数对MPI_SSEND执行影响的问询
关于Fortran中MPI包装子例程从假定大小参数改为假定形状参数对MPI_SSEND执行影响的问询
你好呀,我来帮你梳理这个问题~ 首先要给你点个赞,把旧的假定大小数组(integer :: buf(*))改成通用接口+不同秩的假定形状数组版本,这是非常符合现代Fortran编程规范的改进,也完美解决了你遇到的编译错误。
接下来核心问题:这种改动完全不会影响MPI_SSEND的执行逻辑和正确性,原因主要有这几点:
1. MPI的底层工作逻辑和Fortran数组类型无关
MPI本质上是直接操作连续内存块的,它并不关心Fortran里是用假定大小、假定形状还是显式形状数组传递数据——只要传递给MPI的内存地址指向的是连续的、符合count参数指定长度的有效数据区域,MPI就能正确完成发送操作。
2. 你的三个包装子例程都能正确匹配MPI的内存要求
我们逐个看:
- 标量版本:
mpi_int_ssend_scalar里的buf是单个整数,传递给MPI_SSEND时,它会被当成一段长度为1的连续内存(这里要注意哦,你原来的标量调用里传了count=2,这其实是不符合逻辑的,可能是个小bug,但这和参数类型无关)。 - 向量版本:假定形状数组
integer, dimension(:) :: buf在Fortran中是连续存储的,和原来假定大小数组传递的内存块完全一致,MPI能直接读取所有元素。 - 矩阵版本:Fortran采用列优先存储,假定形状数组
integer, dimension(:,:) :: buf的内存布局和你之前用的假定大小数组完全相同,只要你计算的count参数正确(比如size(mort_no,1)*lnblocks),MPI就能准确发送所有矩阵元素。
额外的小建议
- 可以考虑在标量版本的子例程里强制
count=1,避免调用时传错count值引发错误; - 假定形状数组相比假定大小数组,编译器能提供更严格的类型检查和边界检查,能帮你更早发现代码中的内存访问问题;
- 如果你后续还要扩展其他数据类型的MPI包装,可以继续沿用这种通用接口的模式,代码会更清晰易维护。
补充你提到的代码片段供参考:
原代码中报错的标量调用:
! -> PASSING SCALAR (ERROR GENERATED) call mpi_int_ssend ( & & new_loc(1, i), & & 2, & & MPI_INTEGER, & & child(2, j, i), & & child(1,j,i), & & MPI_COMM_WORLD, & & ierr & & )原假定大小参数的子例程:
subroutine mpi_int_ssend (buf, count, datatype, dest, tag, comm, ierror) use mpi integer :: buf(*) integer :: count, datatype, dest, tag, comm, ierror call mpi_ssend(buf, count, datatype, dest, tag, comm, ierror) return end subroutine mpi_int_ssend新的通用接口和分秩子例程:
interface mpi_int_ssend module procedure mpi_int_ssend_scalar module procedure mpi_int_ssend_vector module procedure mpi_int_ssend_matrix end interface mpi_int_ssend subroutine mpi_int_ssend_scalar (buf, count, datatype, dest, tag, comm, ierror) use mpi integer :: buf integer :: count, datatype, dest, tag, comm, ierror call mpi_ssend(buf, count, datatype, dest, tag, comm, ierror) return end subroutine mpi_int_ssend_scalar subroutine mpi_int_ssend_vector(buf, count, datatype, dest, tag, comm, ierror) use mpi integer, dimension (:) :: buf integer :: count, datatype, dest, tag, comm, ierror call mpi_ssend(buf, count, datatype, dest, tag, comm, ierror) return end subroutine mpi_int_ssend_vector subroutine mpi_int_ssend_matrix(buf, count, datatype, dest, tag, comm, ierror) use mpi integer, dimension (:, :) :: buf integer :: count, datatype, dest, tag, comm, ierror call mpi_ssend(buf, count, datatype, dest, tag, comm, ierror) return end subroutine mpi_int_ssend_matrix
备注:内容来源于stack exchange,提问作者Andris R.




