MPI中的发送和接收缓冲区相同

时间:2015-12-24 12:37:59

标签: c++ mpi

在我的代码中,每个进程都在数组的某个部分上运行。我希望每个进程将其处理的部分发送到其他进程,并从其他进程接收其他部分。为此,我使用MPI_Allgatherv,但我保持发送和接收缓冲区相同:

MPI_Allgatherv (&vel[0],  localSizesFaceV[rank], MPI_DOUBLE, &vel[0],  localSizesFaceV, displsFaceV, MPI_DOUBLE, MPI_COMM_WORLD);

之前我使用此函数用于其他目的,使用不同的发送和接收缓冲区并且它有效。这就是为什么我确信其他参数没有问题。

在2个进程的情况下,其中一个进程不返回。当我将发送缓冲区复制到另一个std::vector

vector <double> vel2;
vel2 = vel;

并使用vel2作为发送缓冲区,然后返回所有进程。为什么呢?

2 个答案:

答案 0 :(得分:6)

一般来说,MPI要求参数不带别名。明确提到chapter 2.3 of the current standard

  

除非另有说明,否则为OUT类型的参数或类型INOUT   不能与传递给MPI过程的任何其他参数别名。

这解释了为什么您的代码有问题。但是,有可能非常轻松地解决您的问题,而无需显式复制缓冲区:MPI_IN_PLACE关键字。它指定在任何相关的地方使用输出缓冲区作为输入缓冲区“就地”完成通信。

您的代码将变为:

MPI_Allgatherv( MPI_IN_PLACE, 0, MPI_TYPE_NULL, &vel[0],  localSizesFaceV, displsFaceV, MPI_DOUBLE, MPI_COMM_WORLD);

注意:用于发送缓冲区的实际类型无关紧要。如果您愿意,可以保留MPI_DOUBLE,但我倾向于使用MPI_TYPE_NULL来明确该参数被忽略。

答案 1 :(得分:2)

来自规范http://www.mpich.org/static/docs/v3.1/www3/MPI_Allgatherv.html

int MPI_Allgatherv(const void *sendbuf, int sendcount, MPI_Datatype sendtype,
               void *recvbuf, const int *recvcounts, const int *displs,
               MPI_Datatype recvtype, MPI_Comm comm)

sendbuf是const,但您也传递了一个指针,允许通过sendbuf更改recvbuf底层内存。这看起来很危险,但我不太了解MPI。

我还假设缓冲存储器上存在可能的竞争条件,如果是这样 - 这是未定义的行为。

相关问题