Fortran MPI_Isend 和 MPI_Irecv
Fortran MPI_Isend and MPI_Irecv
我对 MPI_Isend 和 MPI_Irecv 有疑问:接收向量从未正确发送。
代码是用 Fortran 编写的。
每个进程都有许多我想向其发送一些值的接触进程。我要发送的值由 4 个向量组成,这些向量是每个进程称为 variables
的类型的一部分。
这是我使用的代码:
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)
和 neighbours(i), j, 1)
也不起作用...
接收缓冲区在内存中不连续(因为 Fortran 是主要列)
mpi_irecv(receivedValues(i, j, :)
所以这只有在 MPI_SUBARRAYS_SUPPORTED
是 .true.
时才有效(并且它不在 Open MPI 中,MPICH 和 mpi_f08
绑定可能就是这种情况)。
您不仅得到了不正确的数据,而且还很可能导致静默数据损坏。
您可以重新排序 receivedValues
数组,或使用派生数据类型并使用 receivedValues(i,j,1)
作为接收缓冲区。
我对 MPI_Isend 和 MPI_Irecv 有疑问:接收向量从未正确发送。 代码是用 Fortran 编写的。
每个进程都有许多我想向其发送一些值的接触进程。我要发送的值由 4 个向量组成,这些向量是每个进程称为 variables
的类型的一部分。
这是我使用的代码:
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)
和 neighbours(i), j, 1)
也不起作用...
接收缓冲区在内存中不连续(因为 Fortran 是主要列)
mpi_irecv(receivedValues(i, j, :)
所以这只有在 MPI_SUBARRAYS_SUPPORTED
是 .true.
时才有效(并且它不在 Open MPI 中,MPICH 和 mpi_f08
绑定可能就是这种情况)。
您不仅得到了不正确的数据,而且还很可能导致静默数据损坏。
您可以重新排序 receivedValues
数组,或使用派生数据类型并使用 receivedValues(i,j,1)
作为接收缓冲区。