我正在尝试将并行化实现到我的博士学位论文的 flowsolver 代码中,我继承了一个在预定义子域之间发送数据的子程序。该子程序通过 MPI_Isend 命令发送数据,并使用 MPI_Irecv 命令接收数据,然后调用 waitall。
(有问题的代码如下:)
! -----------------------------------------------------------
! Definition of instant send/receive passings with barrier at the end
! -----------------------------------------------------------
spos=1 ! Position of the first element to send within send array
do i=1,isize ! loop over the number of exchanging segments
if (nsendseg(i).ne.0) then ! choose only domains with something to send
call MPI_ISend(send(spos),nsendseg(i),MPI_REAL8,i-1,1,MPI_COMM_WORLD,reqs(i),ierr)
spos=spos+nsendseg(i)
end if
enddo
rpos=1
do i=1,isize
if (nrecvseg(i).ne.0) then
call MPI_IRecv(recv(rpos),nrecvseg(i),MPI_REAL8,i-1,MPI_ANY_TAG,MPI_COMM_WORLD,reqs(i+sum(nsendseg)),ierr)
rpos=rpos+nrecvseg(i)
end if
end do
if (irank .eq. 0) print *, reqs
call MPI_Waitall(sum(nsendseg)+sum(nrecvseg),reqs,MPI_STATUSES_IGNORE,ierr)
编辑澄清 sum(nsendseg)+sum(nrecvseg):我“相信”(我从一位前博士生那里继承了这段代码,而他自己又从另一位博士生那里继承了这段代码,所以有一些中国传言)nsendseg 代表段(核心)要发送的节点数和发送位置。例如,在 10 个核心上运行时,它们是 10 个整数的数组,表示跨核心的子域之间的共享节点,例如,如果段 3 与段 1 共享 12 个节点,与段 7 共享 3 个节点,而与其他任何段共享 0 个节点,则 nsendseg 为 (12,0,0,0,0,0,3,0,0,0)。任何段接收和发送的节点数都不同,因为许多段可以连接到一个段。这里的想法是每个核心都会遍历所有其他核心的列表,并仅从每个核心发送和接收相关数据。
此代码片段中止,并在部分或全部节点上复制下面的错误。
Abort(336210451) on node 13 (rank 13 in comm 0): Fatal error in PMPI_Waitall: Request pending due to failure, error stack:
PMPI_Waitall(352): MPI_Waitall(count=28734, req_array=0x18ac060, status_array=0x1) failed
PMPI_Waitall(328): The supplied request in array element 2 was invalid (kind=0)
我目前认为这里的错误在于 reqs 数组没有正确传递给它的通信句柄。下面的文本块是 reqs 数组的一个示例,它“感觉”像是 isend 或 irecv 子程序试图放入一个奇怪的数据类型(reqs 是一个默认整数数组)。
0 -1409286132 0 0 -1409286133 -1409286135
-1409286134 0 0 0 0 0
0 0 0 0 0 0
0 0 0 0 0 0
0 0 0 0 0 0
0 0 0 0 0 0
0 0 0 0 0 0
0 0 0 0 0 0
0 0 0 0 0 0
0 0 0 0 0 0
0 0 0 0 0 -1409286131
0 0 -1409286130 -1409286129 -1409286128 0
0 0 0 0 0 0
0 0 0 0 0 0
0 0 0 0 0 0
0 0 0 0 0 0
0 0 0 0 0 0
0 0 0 0 0 0
0 0 0 0 0 0
0 0 0 0 0 0
0 0 0 0 0 0
0 0
我知道这有点像是在瞎猜,因为我基本上是在要求随机的互联网用户猜测一段早已离开的人写的代码的含义。
有人能看到我的错误根源吗,或者告诉我 mpi 通信句柄应该是什么样子,或者任何其他明智的建议,我将不胜感激。<3
您需要
reqs = MPI_REQUEST_NULL
在循环之前进行初始化。等待空请求是有效的,并且会立即成功。在传递给 waitall 的数组中可以有空请求。请求数量的计算似乎很奇怪。您没有显示 reqs 的大小。对于以下解决方案,它的大小应该是 2*isize:
请求数组中没有漏洞的解决方案(请求数量的上限仍为 2*isize):