2

我必须在 FORTRAN 90 中发送和接收(MPI)一大块多维数组。这条线

MPI_Send(x(2:5,6:8,1),12,MPI_Real,....)

根据 Gropp、Lusk 和 Skjellum 的“使用 MPI ...”一书,不应该使用。做这个的最好方式是什么?我是否必须创建一个临时数组并将其发送或使用MPI_Type_Create_Subarray或类似的东西?

4

2 回答 2

4

不使用数组部分的原因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_f08MPI-3的新界面已经利用了这一点。

非阻塞调用在 Fortran 中提出了更大的问题,超出了 Alexander Vogt 的描述。原因是Fortran 没有抑制编译器优化的概念(即volatileFortran 中没有关键字)。以下代码可能无法按预期运行:

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 的编译器也不会求助于缓冲区参数的寄存器优化。

于 2013-10-19T09:49:32.693 回答
0

编辑:正如 Hristo Iliev 指出MPI_Send的那样总是阻塞的,但可能会选择异步发送数据。从这里

在您可以使用发送缓冲区之前,MPI_Send 不会返回。

MPI_Send当涉及非连续数组时,非阻塞通信(如)可能会给 Fortran 带来问题。然后,编译器为虚拟变量创建一个临时数组并将其传递给子例程。一旦子例程完成,编译器就可以自由地释放该副本的内存。

只要您使用阻塞通信 ( MPI_Send) 就可以了,因为当子例程返回时消息已经发送。然而,对于非阻塞通信 ( MPI_Isend),临时数组是发送缓冲区,子程序在发送之前返回。

因此,MPI 可能会从不再包含有效数据的内存位置发送数据。

因此,要么您自己创建一个副本(以便您的发送缓冲区在内存中是连续的),要么您创建一个子数组(即告诉 MPI 您要发送的元素在内存中的地址)。还有其他选择,例如MPI_Pack,但我没有使用它们的经验。

哪种方式更快?好吧,这取决于:

  • 关于 MPI 库的实际实现
  • 关于数据及其分布
  • 在你的编译器上
  • 在您的硬件上

有关详细说明和更多选项,请参见此处

于 2013-10-18T18:48:54.933 回答