我必须在 FORTRAN 90 中发送和接收(MPI)一大块多维数组。这条线
MPI_Send(x(2:5,6:8,1),12,MPI_Real,....)
根据 Gropp、Lusk 和 Skjellum 的“使用 MPI ...”一书,不应该使用。做这个的最好方式是什么?我是否必须创建一个临时数组并将其发送或使用MPI_Type_Create_Subarray
或类似的东西?
我必须在 FORTRAN 90 中发送和接收(MPI)一大块多维数组。这条线
MPI_Send(x(2:5,6:8,1),12,MPI_Real,....)
根据 Gropp、Lusk 和 Skjellum 的“使用 MPI ...”一书,不应该使用。做这个的最好方式是什么?我是否必须创建一个临时数组并将其发送或使用MPI_Type_Create_Subarray
或类似的东西?
不使用数组部分的原因MPI_SEND
是编译器必须使用一些MPI 实现创建一个临时副本。这是因为 Fortran 只能正确地将数组部分传递给具有显式接口的子例程,并且在所有其他情况下必须生成临时的“扁平化”副本,通常在调用子例程的堆栈上。不幸的是,在将 TR 29113 扩展为 F2008 之前的 Fortran 中,没有办法声明采用可变类型参数的子例程,并且 MPI 实现通常诉诸语言技巧,例如MPI_Send
完全用 C 实现并依赖 Fortran 始终将数据作为指针传递。
一些 MPI 库通过生成大量重载来解决此问题MPI_SEND
:
INTEGER
INTEGER
INTEGER
然后对CHARACTER
, LOGICAL
,DOUBLE PRECISION
等重复相同的操作。这仍然是一种技巧,因为它不包括传递用户定义类型的情况。此外,它使 C 实现变得非常复杂,因为它现在必须理解 Fortran 数组描述符,这些描述符是非常特定于编译器的。
幸运的是时代在变。Fortran 2008 的 TR 29113 扩展包括两个新功能:
TYPE(*)
DIMENSION(..)
两者的组合,即TYPE(*), DIMENSION(..), INTENT(IN) :: buf
,描述了一个既可以是不同类型又可以具有任何维度的参数。mpi_f08
MPI-3的新界面已经利用了这一点。
非阻塞调用在 Fortran 中提出了更大的问题,超出了 Alexander Vogt 的描述。原因是Fortran 没有抑制编译器优化的概念(即volatile
Fortran 中没有关键字)。以下代码可能无法按预期运行:
INTEGER :: data
data = 10
CALL MPI_IRECV(data, 1, MPI_INTEGER, 0, 0, MPI_COMM_WORLD, req, ierr)
! data is not used here
! ...
CALL MPI_WAIT(req, MPI_STATUS_IGNORE, ierr)
! data is used here
有人可能会期望在调用 to 之后MPI_WAIT
data
会包含从 rank 0 接收到的值,但很可能并非如此。原因是编译器无法知道返回data
后可能会异步更改MPI_IRECV
,因此将其值保存在寄存器中。这就是为什么非阻塞 MPI 调用在 Fortran 中通常被认为是危险的。
TR 29113 也通过ASYNCHRONOUS
属性解决了第二个问题。如果你看一下 的mpi_f08
定义MPI_IRECV
,它的buf
参数被声明为:
TYPE(*), DIMENSION(..), INTENT(OUT), ASYNCHRONOUS :: buf
即使buf
是一个标量参数,即没有创建临时副本,符合 TR 29113 的编译器也不会求助于缓冲区参数的寄存器优化。
编辑:正如 Hristo Iliev 指出MPI_Send
的那样总是阻塞的,但可能会选择异步发送数据。从这里:
在您可以使用发送缓冲区之前,MPI_Send 不会返回。
MPI_Send
当涉及非连续数组时,非阻塞通信(如)可能会给 Fortran 带来问题。然后,编译器为虚拟变量创建一个临时数组并将其传递给子例程。一旦子例程完成,编译器就可以自由地释放该副本的内存。
只要您使用阻塞通信 ( MPI_Send
) 就可以了,因为当子例程返回时消息已经发送。然而,对于非阻塞通信 ( MPI_Isend
),临时数组是发送缓冲区,子程序在发送之前返回。
因此,MPI 可能会从不再包含有效数据的内存位置发送数据。
因此,要么您自己创建一个副本(以便您的发送缓冲区在内存中是连续的),要么您创建一个子数组(即告诉 MPI 您要发送的元素在内存中的地址)。还有其他选择,例如MPI_Pack
,但我没有使用它们的经验。
哪种方式更快?好吧,这取决于:
有关详细说明和更多选项,请参见此处。