Fortran MPI非阻塞发送/接收中的请求数组

Fortran MPI非阻塞发送/接收中的请求数组,fortran,mpi,nonblocking,Fortran,Mpi,Nonblocking,我试图用Fortran语言重现C语言的例子。到目前为止,我的代码是: use mpi implicit none integer, parameter :: maxn = 8 integer, allocatable :: xlocal(:,:) integer :: i, j, lsize, errcnt, toterr, buff integer :: ierror, nproc, pid, root = 0, nreq = 0 integer, allocatable :: requ

我试图用Fortran语言重现C语言的例子。到目前为止,我的代码是:

use mpi

implicit none
integer, parameter :: maxn = 8
integer, allocatable :: xlocal(:,:)

integer :: i, j, lsize, errcnt, toterr, buff

integer :: ierror, nproc, pid, root = 0, nreq = 0
integer, allocatable :: request(:), status(:,:)

call MPI_INIT(ierror)
call MPI_COMM_SIZE(MPI_COMM_WORLD, nproc, ierror)
call MPI_COMM_RANK(MPI_COMM_WORLD, pid, ierror)

if (mod(maxn, nproc) /= 0) then
    write(*,*) 'Array size (maxn) should be a multiple of the number of processes'
    call MPI_ABORT(MPI_COMM_WORLD, 1, ierror)
end if

lsize = maxn/nproc

allocate(xlocal(0:lsize+1, maxn))
allocate(request(nproc))
allocate(status(MPI_STATUS_SIZE,nproc))

xlocal(0,:) = -1
xlocal(1:lsize,:) = pid
xlocal(lsize+1,:) = -1

! send down unless on bottom
if (pid < nproc-1) then
    nreq = nreq + 1
    call MPI_ISEND(xlocal(lsize,:), maxn, MPI_INTEGER, &
                  pid+1, 0, MPI_COMM_WORLD, request(nreq), ierror)
    write(*,'(2(A,I1),A)') 'process ', pid, ' sent to process ', pid+1, ':'
    write(*,*) xlocal(lsize,:)
end if

if (pid > 0) then
    nreq = nreq + 1
    call MPI_IRECV(xlocal(0,:), maxn, MPI_INTEGER, &
                  pid-1, 0, MPI_COMM_WORLD, request(nreq), ierror)
    write(*,'(2(A,I1),A)') 'process ', pid, ' received from process ', pid-1, ':'
    write(*,*) xlocal(0,:)
end if

! send up unless on top
if (pid > 0) then
    nreq = nreq + 1
    call MPI_ISEND(xlocal(1,:), maxn, MPI_INTEGER, &
                  pid-1, 1, MPI_COMM_WORLD, request(nreq), ierror)
    write(*,'(2(A,I1),A)') 'process ', pid, ' sent to process ', pid-1, ':'
    write(*,*) xlocal(1,:)
end if

if (pid < nproc-1) then
    nreq = nreq + 1
    call MPI_IRECV(xlocal(lsize+1,:), maxn, MPI_INTEGER, &
                  pid+1, 1, MPI_COMM_WORLD, request(nreq), ierror)
    write(*,'(2(A,I1),A)') 'process ', pid, ' received from process ', pid+1, ':'
    write(*,*) xlocal(lsize+1,:)
end if

call MPI_WAITALL(nreq, request, status, ierror)

! check results
errcnt = 0
do i = 1, lsize
    do j = 1, maxn
        if (xlocal(i,j) /= pid) errcnt = errcnt + 1
    end do
end do
do j = 1, maxn
    if (xlocal(0,j) /= pid-1) errcnt = errcnt + 1
    if ((pid < nproc-1) .and. (xlocal(lsize+1,j) /= pid+1)) errcnt = errcnt + 1
end do

call MPI_REDUCE(errcnt, toterr, 1, MPI_INTEGER, MPI_SUM, 0, MPI_COMM_WORLD)

if (pid == root) then
    if (toterr == 0) then
        write(*,*) "no errors found"
    else
        write(*,*) "found ", toterr, " errors"
    end if
end if

deallocate(xlocal)
deallocate(request)
deallocate(status)

call MPI_FINALIZE(ierror)
使用mpi
隐式无
整数,参数::maxn=8
整数,可分配::xlocal(:,:)
整数::i,j,lsize,errcnt,toterr,buff
整数::ierror,nproc,pid,root=0,nreq=0
整数,可分配::请求(:),状态(:,:)
调用MPI_INIT(ierror)
呼叫MPI_通信大小(MPI_通信世界、nproc、ierror)
调用MPI_COMM_RANK(MPI_COMM_WORLD、pid、ierror)
如果(mod(maxn,nproc)/=0),则
写入(*,*)“数组大小(maxn)应为进程数的倍数”
调用MPI_中止(MPI_通信世界,1,ierror)
如果结束
lsize=maxn/nproc
分配(xlocal(0:lsize+1,maxn))
分配(请求(nproc))
分配(状态(MPI\U状态\U大小,nproc))
xlocal(0,:)=-1
xlocal(1:lsize,:)=pid
xlocal(lsize+1,:)=-1
! 除非在底部,否则请往下送
如果(pid0),则
nreq=nreq+1
调用MPI_IRECV(xlocal(0,:),maxn,MPI_INTEGER&
pid-1,0,MPI通信世界,请求(nreq),ierror)
写入(*,”(2(A,I1),A)“进程”,pid,“从进程接收”,pid-1:”
写入(*,*)xlocal(0,:)
如果结束
! 送上去,除非在上面
如果(pid>0),则
nreq=nreq+1
调用MPI_ISEND(xlocal(1,:),maxn,MPI_INTEGER&
pid-1,1,MPI通信世界,请求(nreq),ierror)
写入(*,'(2(A,I1),A)'process',pid',发送到process',pid-1',:'
写入(*,*)xlocal(1,:)
如果结束
如果(pid
但我遇到了分段错误,无法找出原因。我感觉这是由于请求数组。有人能解释一下在Fortran中使用请求数组的正确方法吗?我找到的所有参考资料都没有阐明这一点


THX预先

< P>如果你还没有这样做,考虑编译你的程序,一些标志可以帮助你调试,例如用<代码> GoFrTRAN < /C> >,你可以使用<代码> -O0-G-FLAND检查< /C>(如果没有帮助,你可以添加<代码> -fSANTIZZ=地址>代码>版本>=4.8)。其他编译器也有类似的调试选项

这样做,并运行两个进程,您可以在
MPI\u Reduce
行编程崩溃。如果您查找规范(例如),您可以看到此子例程还需要一个参数,即您忘记在末尾添加
ierror
参数

虽然mpi模块中的子程序可以通过
use
关联访问,因此应该检查参数一致性以避免这些小错误,但并非所有子程序都必须在该模块中,这有点悲惨。我不知道您使用的是哪种MPI实现,但我检查了本地MPICH安装,它在模块中没有大多数子例程,因此不存在用于它们的显式接口。我猜您也处于类似的情况,但我猜其他实现可能会遭遇类似的命运。您可以将其与缺少
MPI\u Reduce
函数原型的C头文件进行比较。我想这是因为最初大多数实现只有Fortran 77接口


最后的一些评论:注意不要只是复制粘贴C代码。您传递的数组不是连续的,将导致一个临时副本被传递到MPI例程,这是非常低效的(在这种情况下这并不重要)。

thx获取关于标志和数组的答案和提示!奇怪的tho;代码在阻止send/recv.offtopic时运行良好,-fsanize=address到底做了什么?它激活了以下用法: