我有一些Fortran代码,我正在与MPI并行化,这正在做着真正奇怪的事情。首先,我有一个变量nstartg,我从老板流程向所有工人广播:
call mpi_bcast(nstartg,1,mpi_integer,0,mpi_comm_world,ierr)
变量nstartg
永远不会在程序中再次更改。稍后,我让老板进程向工作人员发送数组eproc
的{{1}}元素:
edge
如果if (me==0) then
do n=1,ntasks-1
(determine the starting point estart and the number eproc
of values to send)
call mpi_send(edge(estart),eproc,mpi_integer,n,n,mpi_comm_world,ierr)
enddo
endif
非零,则使用匹配的接收语句。 (为了便于阅读,我省略了其他一些代码;我有一个很好的理由不使用scatterv。)
以下事情变得奇怪:变量me
变为nstartg
而不是保持其实际值。例如,在进程1上,在mpi_recv,n
之后,在进程2上,它等于2,依此类推。此外,如果我将上面的代码更改为
nstartg = 1
并在匹配调用mpi_recv时相应地更改标记,然后在进程1,nstartg = 1234568;在过程2,nstartg = 1234569等
到底是怎么回事?我改变的是mpi_send / recv用于识别消息的标签;如果标签是唯一的,那么消息不会混淆,这不应该改变任何东西,但它改变了一个完全不相关的变量。
在boss过程中,call mpi_send(edge(estart),eproc,mpi_integer,n,n+1234567,mpi_comm_world,ierr)
没有改变,所以我可以通过再次播放来解决这个问题,但这不是一个真正的解决方案。最后,我应该提一下,使用电栅栏编译和运行此代码并没有发现任何缓冲区溢出,也没有--fbounds-check向我抛出任何东西。
答案 0 :(得分:5)
最可能的原因是您将INTEGER
标量作为实际status
参数传递给MPI_RECV
,当它应该真正声明为具有特定于实现的大小的数组时,可用作为MPI_STATUS_SIZE
常数:
INTEGER, DIMENSION(MPI_STATUS_SIZE) :: status
或
INTEGER status(MPI_STATUS_SIZE)
通过接收操作将消息标记写入其中一个状态字段(其特定于实现的索引可用作MPI_TAG
常量,字段值可以作为status(MPI_TAG)
访问)并且如果你的status
只是一个标量INTEGER
,然后其他几个局部变量会被覆盖。在您的情况下,它只是发生了nstartg
落在堆栈中的status
之上。
如果您不关心接收状态,则可以改为传递特殊常量MPI_STATUS_IGNORE
。