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 型の数学規則を正しく理解していれば、どちらも完了しないはずです。

4

1 に答える 1

3

明らかに 2 番目のプログラムでは、ランク 0 が自分自身に送信しており、ランク 1 も自分自身からのメッセージを期待しています。

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

宛先ランクは 0 ではなく 1 にする必要があります

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

ソースランクは 1 ではなく 0 にする必要があります。

そうしないと、MPI タイプのマッチングが正しく理解できません。両端の型マップの基になるプリミティブ型が一致する必要があることのみを示しています。型マップが 20 個のプリミティブ整数を持つベクトルを作成しています。このタイプの要素を 1 つ送信すると、メッセージには実際には 20 個の整数が含まれます。レシーバー側では、少なくとも 20 の整数用のスペースを提供するので、これは正しいです。その逆も正しい。

2 番目のプログラムで 10 個または 18 個の整数のみを送信すると、ベクトル型の完全な要素が作成されないため、正しくありません。それにもかかわらず、受信操作は完了しますがMPI_Get_count()、ステータスを呼び出すと、MPI_UNDEFINED受信したプリミティブ整数要素の数から整数のベクトル要素を構築できないため、返されます。MPI_DOUBLEsend (または vector、または structure、または double を持つその他の型) などのプリミティブ型を混在させて として受け取ることも正しくありませんMPI_INT

また、MPI メッセージは型マップや型 ID を持たないため、ほとんどの MPI 実装では型が一致するかどうかをチェックしないことに注意してください。として送受信することは可能ですが(ほとんどのシステムではどちらも 4 バイトであるため)、そうするのは正しくありません。MPI_FLOATMPI_INT

于 2012-05-19T11:37:21.387 に答える