Parallel processing Fortran MPI_Isend和MPI_Irecv

Parallel processing Fortran MPI_Isend和MPI_Irecv,parallel-processing,fortran,mpi,fortran90,openmpi,Parallel Processing,Fortran,Mpi,Fortran90,Openmpi,我对MPI_Isend和MPI_Irecv有一个问题:接收向量从未正确发送。 代码是用Fortran编写的 每个进程都有许多触摸进程,我想向它们发送一些值。我要发送的值由4个向量组成,它们是每个进程的变量类型的一部分 以下是我使用的代码: program isend_test use mpi real, dimension(:,:,:), allocatable :: receivedValues real, dimension(:,:), allocatable :: sendReals i

我对MPI_Isend和MPI_Irecv有一个问题:接收向量从未正确发送。 代码是用Fortran编写的

每个进程都有许多触摸进程,我想向它们发送一些值。我要发送的值由4个向量组成,它们是每个进程的
变量类型的一部分

以下是我使用的代码:

program isend_test
use mpi

real, dimension(:,:,:), allocatable :: receivedValues
real, dimension(:,:), allocatable :: sendReals
integer, dimension(:,:), allocatable :: requestSend
integer, dimension(:,:), allocatable :: requestReceive
integer, dimension(:), allocatable :: neighbours
integer, dimension(mpi_status_size) :: status
integer :: ierr, currentNeighbour, k, me, nTasks, nValues, nNeighbours, addedNeighbours

call MPI_init(ierr)

call MPI_COMM_RANK(MPI_COMM_WORLD, me, ierr)
call MPI_COMM_SIZE(MPI_COMM_WORLD, nTasks, ierr)

nNeighbours = 2

! Only 3 values for each variable to keep it simple
nValues = 3

allocate(receivedValues(nNeighbours,4,nValues))
allocate(sendReals(4,nValues))
allocate(requestSend(4,nNeighbours))
allocate(requestReceive(4,nNeighbours))
allocate(neighbours(2))

receivedValues = -9999

! Initializing neighbours - Every process is adjacent to every other process in this example
addedNeighbours = 0
do j = 0,2
    if (j == me) then
        cycle
    endif
    addedNeighbours = addedNeighbours + 1
    neighbours(addedNeighbours) = j
enddo

! fill in some values to send
do j = 1,4
   do i=1,nValues
      sendReals(j,i) = j + 10*me + 100*i
   enddo
enddo

do j = 1,4
    do i = 1,nNeighbours
        call mpi_isend(sendReals(j,:), nValues, mpi_real, neighbours(i), j, MPI_COMM_WORLD, requestSend(j,i), ierr)
        call mpi_irecv(receivedValues(i, j, :), nValues, mpi_real, neighbours(i), j, MPI_COMM_WORLD, requestReceive(j,i), ierr)
    enddo
enddo


do j = 1,4
    do i = 1,nNeighbours
        call mpi_wait(requestSend(j,i), status, ierr)
        call mpi_wait(requestreceive(j,i), status, ierr)
    enddo
enddo

write(*,*)receivedValues

call MPI_finalize(ierr)
end
我知道数据类型是正确的(它们与
MPI_Send
MPI_Recv
一起工作),并且邻域和标记的整个匹配也是正确的,因为代码正确运行。但是,如果我在同步之前在开始时设置了
receivedValues=-9999
,则不会更改这些值

我知道代码可以做得更有效,但我改变了太多,发现错误没有成功。。。有人有主意吗?这可能是缓冲区的问题,我就是找不到


顺便说一句:发送和接收
sendReals(j,1)
邻居(i,j,1)
也不起作用…

接收缓冲区在内存中不是连续的(因为Fortran是主要列)

因此,只有当所支持的
MPI\u子阵列
.true.
(并且它不在开放的MPI中,可能是MPICH和
MPI\u f08
绑定的情况)时,这才可以工作

您不仅获得了不正确的数据,而且很可能导致静态数据损坏


您可以对
receivedValues
数组重新排序,或者使用派生数据类型并使用
receivedValues(i,j,1)
作为接收缓冲区。

您可能已经知道您的代码有不匹配的括号,并且很难按原样编译。StackOverflow提倡使用MCVE公式化的问题,因此请修复代码“C”-完整性,以便既能编译无错误,又能再现所声称的问题,否则不符合“V”-验证性。您有4个*nNeighbours isend/irecv对,但只有nNeighbour wait对,所以您的程序不可能是正确的-每个异步通信都必须有相应的等待,如果不正确,您的程序是不正确的。@user3666197:您是对的,对不起。我修改了我的代码,使它更容易阅读,但在这样做时犯了一些错误。谢谢你的提醒。@Ian Bush:这太尴尬了,一个非常明显的错误。非常感谢。如果这不能解决这个问题,我将再次发布完整的版本。你也可以看看mpi_waitall,它会稍微简化代码,这比预期的要简单,改变
receivedValues
的顺序就做到了。非常感谢你!
mpi_irecv(receivedValues(i, j, :)