1

我有一些 Fortran 代码,我正在与 MPI 并行化,它正在做真正奇怪的事情。首先,有一个变量 nstartg 我从老板进程广播给所有工人:

call mpi_bcast(nstartg,1,mpi_integer,0,mpi_comm_world,ierr)

该变量nstartg在程序中不再更改。稍后,我让老板进程将eproc数组的元素发送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

me如果非零,则带有匹配的接收语句。(为了便于阅读,我省略了一些其他代码;我不使用 scatterv 是有充分理由的。)

这就是事情变得奇怪的地方:变量nstartg被更改为n而不是保持其实际值。例如,在进程 1 上,在 mpi_recv 之后nstartg = 1,在进程 2 上它等于 2,依此类推。此外,如果我将上面的代码更改为

call mpi_send(edge(estart),eproc,mpi_integer,n,n+1234567,mpi_comm_world,ierr)

并在对 mpi_recv 的匹配调用中相应地更改标签,然后在进程 1 上,nstartg = 1234568; 在进程 2 上,nstartg = 1234569 等。

到底是怎么回事?我改变的只是 mpi_send/recv 用来识别消息的标签;如果标签是唯一的,这样消息就不会混淆,这不应该改变任何东西,但它正在改变一个完全不相关的变量。

在boss进程中,nstartg没有改变,所以我可以通过再次广播来解决这个问题,但这并不是一个真正的解决方案。最后,我应该提一下,使用电子围栏编译和运行这段代码并没有发现任何缓冲区溢出,-fbounds-check 也没有向我抛出任何东西。

4

1 回答 1

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改为传递特殊常量。

于 2012-12-06T08:17:57.953 回答