1

MPI_Isendをランダムな宛先に送信するのに問題があります。宛先をハードコーディングすると正常に機能しますが、ランダムに生成しようとすると機能しません。関連するコードは次のとおりです。

    MPI_Init(&argc,&argv);
    MPI_Comm_size(MPI_COMM_WORLD,&numprocs);
    MPI_Comm_rank(MPI_COMM_WORLD,&myid);
    srand48(myid);
    request=MPI_REQUEST_NULL;
    if(myid == 0){
            buffer=drand48();
            do {
                    destination=lrand48() % numprocs;
            } while (destination == 0); //Prevent sending to self
            MPI_Isend(&buffer,1,MPI_DOUBLE,destination,1234,MPI_COMM_WORLD,&request);

    }
    else if (myid == destination) {
            MPI_Irecv(&buffer,1,MPI_DOUBLE,MPI_ANY_SOURCE,MPI_ANY_TAG,MPI_COMM_WORLD,&request);

    }
    if(myid == 0){
            printf("processor %d  sent %lf to %d\n",myid,buffer,destination);
    }
    else {
            printf("processor %d  got %lf\n",myid,buffer);
    }

私はうまくコンパイルすることができます私が出力でmpicc main.c プログラムを実行するときmpirun -np 4 ./a.out

processor 0  sent 0.170828 to 2
processor 1  got 0.000000
processor 2  got 0.000000
processor 3  got 0.000000

たとえば、宛先を2としてハードコーディングすると、期待どおりの出力が得られます。

processor 0  sent 0.170828
processor 1  got 0.000000
processor 2  got 0.170828
processor 3  got 0.000000
4

1 に答える 1

1

MPI_Isend対応する非ブロッキング操作を開始しますMPI_Irecv またはファミリrequestから返されたハンドルを関数に渡す前に、それらが終了するという保証はありません(テスト関数が使用されている場合、要求の完了状態はブール変数で通知され、それが完了するまでは完了しません)ブールフラグはfalseのままなので)。MPI_WaitMPI_Test

ただし、コードには概念上の問題があります。MPIは分散メモリパラダイムです。各MPIランクは、実際には個別のアドレス空間に存在します(ただし、標準では厳密には要求されていませんが、これは事実上すべてのMPI実装が提供するものです)。したがってdestination、ランク0に設定しても、その値は他のプロセスに魔法のように転送されません。その値を最初にブロードキャストするか、特別な「空の」メッセージを他のすべてのランクに送信することができます。次に例を示します。

if (myid == 0) {
   MPI_Request reqs[numprocs];

   buffer=drand48();
   do {
      destination=lrand48() % numprocs;
   } while (destination == 0); //Prevent sending to self
   for (i = 1; i < numprocs; i++) {
      if (i == destination)
         MPI_Isend(&buffer,1,MPI_DOUBLE,i,1234,MPI_COMM_WORLD,&reqs[i]);
      else
         // Send an empty message with different tag
         MPI_Isend(&buffer,0,MPI_DOUBLE,i,4321,MPI_COMM_WORLD,&reqs[i]);
   }
   reqs[0] = MPI_REQUEST_NULL;
   MPI_Waitall(numprocs, reqs, MPI_STATUSES_IGNORE);     
   printf("processor %d  sent %lf to %d\n",myid,buffer,destination);
}
else {
   MPI_Status status;

   MPI_Recv(&buffer,1,MPI_DOUBLE,MPI_ANY_SOURCE,MPI_ANY_TAG,MPI_COMM_WORLD,&status);
   if (status.MPI_TAG == 1234)
      printf("processor %d  got %lf\n",myid,buffer);
}

ブロードキャストでは、コードは次のようになります。

request=MPI_REQUEST_NULL;
if (myid == 0) {
   buffer=drand48();
   do {
      destination=lrand48() % numprocs;
   } while (destination == 0); //Prevent sending to self
   MPI_Bcast(&destination,1,MPI_INT,0,MPI_COMM_WORLD);
   MPI_Isend(&buffer,1,MPI_DOUBLE,destination,1234,MPI_COMM_WORLD,&request);
}
else {
   MPI_Bcast(&destination,1,MPI_INT,0,MPI_COMM_WORLD);
   if (myid == destination) {
      MPI_Irecv(&buffer,1,MPI_DOUBLE,MPI_ANY_SOURCE,MPI_ANY_TAG,MPI_COMM_WORLD,&request);
   }
}
MPI_Wait(&request, MPI_STATUS_IGNORE);
if (myid == 0) {
   printf("processor %d  sent %lf to %d\n",myid,buffer,destination);
}
else {
   printf("processor %d  got %lf\n",myid,buffer);
}
于 2013-02-19T19:17:07.313 に答える