MPI类型匹配

4
我想知道为什么这个程序在MPI中运行(openMPI 1.5/1.6)正常。
#include <stdio.h>
#include <mpi.h>

#define VECTOR_SIZE 100

int main(int argc,char ** argv) {
  int A[VECTOR_SIZE];
  int sub_size=2;
  int count=10;
  MPI_Datatype partial_array;
  int rank,size;
  MPI_Status status;

  MPI_Init(&argc,&argv);
  MPI_Comm_rank(MPI_COMM_WORLD,&rank);
  MPI_Comm_size(MPI_COMM_WORLD,&size);

  MPI_Type_vector(count, sub_size,
          2*sub_size, MPI_INT, &partial_array);

  MPI_Type_commit(&partial_array);

  if (rank == 0) {
    int i;
    // server - initialize data and send
    for (i = 0; i< VECTOR_SIZE; i++) {   
      A[i] = i;
    }
    MPI_Send(&(A[0]), 1, partial_array, 1, 0, MPI_COMM_WORLD);
  } else if (rank==1) {
    int i;
    for (i = 0; i< VECTOR_SIZE; i++) {

        A[i] = 0;

    }
    // vector is composed by 20 MPI_INT elements
    MPI_Recv(&(A[0]),20, MPI_INT, 0, 0, MPI_COMM_WORLD, &status);

    printf("\n");

    for (i = 0; i<VECTOR_SIZE; i++) {
      printf("%d ",A[i]);

    }
    printf("\n");
  }

  MPI_Finalize();

}

而这个程序中,发送和接收原语被交换,但是程序不会终止(接收操作永远不会完成):

#include <stdio.h>
#include <mpi.h>

#define VECTOR_SIZE 100

int main(int argc,char ** argv) {
    int A[VECTOR_SIZE];
    int sub_size=2;
    int count=10;
    MPI_Datatype partial_array;
    int rank,size;
    MPI_Status status;

    MPI_Init(&argc,&argv);
    MPI_Comm_rank(MPI_COMM_WORLD,&rank);
    MPI_Comm_size(MPI_COMM_WORLD,&size);

    MPI_Type_vector(count, sub_size,
                    2*sub_size, MPI_INT, &partial_array);

    MPI_Type_commit(&partial_array);

    if (rank == 0) {
        int i;
        // server - initialize data and send
        for (i = 0; i< VECTOR_SIZE; i++) {

            A[i] = i;

        }
        MPI_Send(&(A[0]),20, MPI_INT, 0, 0, MPI_COMM_WORLD);

    } else if (rank==1) {
        int i;
        // client - receive data and print
        for (i = 0; i< VECTOR_SIZE; i++) {

            A[i] = 0;

        }

        MPI_Recv(&(A[0]), 1, partial_array, 1, 0, MPI_COMM_WORLD, &status);

        printf("\n");

        for (i = 0; i<VECTOR_SIZE; i++) {
            printf("%d ",A[i]);

        }
        printf("\n");
    }

    MPI_Finalize();

}

如果我正确理解MPI类型匹配规则,那么这两个都不应该完成。
1个回答

3
很明显,在第二个程序中,排名为0的进程正在向自己发送消息,而排名为1的进程也期望从自己接收消息。
MPI_Send(&(A[0]),20, MPI_INT, 0, 0, MPI_COMM_WORLD);

目标排名应为1,而不是0

MPI_Recv(&(A[0]), 1, partial_array, 1, 0, MPI_COMM_WORLD, &status);

源排名应该是0,而不是1。

否则,您将无法正确理解MPI类型匹配。它仅说明两端的类型映射中的基本原始类型应该匹配。您正在创建一个类型映射具有20个整数的向量。如果您发送此类型的一个元素,则您的消息实际上将包含20个整数。在接收方,您至少提供了20个整数的空间,因此这是正确的。相反也是正确的。

如果您在第二个程序中仅发送10或18个整数,则不正确,因为它们不会构成向量类型的完整元素。尽管如此,接收操作将完成,但如果您在状态上调用MPI_Get_count(),则会返回MPI_UNDEFINED,因为从接收到的原始整数元素数量无法构造整数数量的向量元素。将原始类型混合使用也是不正确的,例如将MPI_DOUBLE(或向量、结构或其他具有双精度浮点数的类型)发送并将其作为MPI_INT接收。

还请注意,MPI消息不携带其类型映射或类型ID,因此大多数MPI实现不会检查类型是否匹配。可以将MPI_FLOAT发送并将其作为MPI_INT接收(因为在大多数系统上都是4个字节),但这样做是不正确的。


好的,那是一个愚蠢的错误。但是,为什么它能工作呢?发送和接收的MPI数据类型不匹配。 - igon
1
@igon:发送端和接收端的数据类型不需要完全匹配,只有数据类型和数量是重要的。发送进程可以使用任何类型映射来打包10个整数,接收进程可以使用包含10个整数的任何类型映射来接收该消息。 - suszterpatt
抱歉,我没有看到你问为什么类型不匹配时它能够工作。我已经相应地扩展了答案。 - Hristo Iliev
2
在MPI编程中,混合使用具有相同底层数字和元素类型的不同(用户定义)类型在通信的两端实际上是一种经常使用的方法。例如,在发送方,可以使用跨步向量来发送子矩阵,在接收方,则可以使用连续(或仅基本的)类型将子矩阵组装成内存中的单个块。 - Hristo Iliev

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接