【发布时间】:2016-02-05 15:22:33
【问题描述】:
对 MPI 有一些经验,但对派生类型等一些更高级的方面没有经验,这是我的问题所涉及的。
我正在处理的代码有几个尺寸为(-1:nx+2,-1:ny+2,-1:nz+2) 的数组。为了清楚起见,每个进程都有自己的值nx、ny 和nz。数组之间有重叠。例如,一个 proc 上的 x(:,:,-1:2) 将表示与“下方”proc 上的 x(:,:,nz-1:nz+2) 相同的信息。
已定义派生的cell_zface 类型:
idir = 3
sizes = (/nx_glb, ny_glb, nz_glb/) !These nums are the same for all procs.
subsizes = (/nx, ny, 2/)
mpitype = MPI_DATATYPE_NULL
CALL MPI_TYPE_CREATE_SUBARRAY(3, sizes, subsizes, starts, &
MPI_ORDER_FORTRAN, mpireal, mpitype, errcode)
CALL MPI_TYPE_COMMIT(mpitype, errcode)
cell_zface = mpitype
现在,这个派生类型在多个MPI_SENDRECV 调用中成功使用。例如
CALL MPI_SENDRECV( &
x(-1,-1, 1), 1, cell_zface, proc_z_min, tag, &
x(-1,-1,nz+1), 1, cell_zface, proc_z_max, tag, &
comm, status, errcode)
据我了解,此调用是在 procs 之间发送和接收数组的两个“水平”切片(即 x-y 切片)。
我想做一些不同的事情,即发送四个“水平”切片。所以我试试
call mpi_send(x(-1,-1,nz-1), 2, cell_zface, &
proc_z_max, rank, comm, mpierr)
附带接收。
最后,我的问题:代码运行,但错误。 AFAICT,即使我使用“2”而不是“1”作为计数参数,它也只发送两个水平切片。我可以通过两次调用 mpi_send 来解决这个问题:
call mpi_send(x(-1,-1,nz-1), 1, cell_zface, &
proc_z_max, rank, comm, mpierr)
call mpi_send(x(-1,-1,nz+1), 1, cell_zface, &
proc_z_max, rank, comm, mpierr)
附带接收,但这肯定不漂亮。
那么,为什么mpi_send 只发送两个水平切片,即使我将计数参数设置为“2”?有没有一种干净的方式来做我想做的事情?
【问题讨论】:
-
你必须明白,即使你有自己的“类型”,你真正拥有的是一个巨大的连续内存块。因此,虽然您可以发送两个
cell_zface类型,但类型本身在内存中的大小仅与您的类型使用的第一个和最后一个(一维)内存位置之间的距离一样大。 Aka,您的类型的大小不是真正的nx*ny*nz。 -
要完成你想做的事情,你必须给你的派生数据类型一个不同的范围。请注意,数据类型的大小将相同,但“范围”(或此数据类型的连续版本将包含的内存量)将不同。我相信您可以通过MPI_Type_create_resized 完成此操作。
标签: fortran mpi fortran90 fortran95 derived-types