0

私はMPIを初めて使用し、Foxのアルゴリズムの実装を作成しようとしています(AxB = C、ここでAとBは次元nxnの行列です)。私のプログラムは正常に動作しますが、行列Bのブロックのシフト中の通信を積行列の計算とオーバーラップさせることによって具体的に高速化できるかどうかを確認したいと思います(Bのブロック行列はアルゴリズム)。2Dデカルトグリッドの各プロセスには、アルゴリズムに従って、行列A、B、およびCからのブロックがあります。私が現在持っているのはこれです。これはFoxのアルゴリズムの中にあります

if (stage > 0){  


   //shifting b values in all proccess

    MPI_Bcast(a_temp, n_local*n_local, MPI_DOUBLE, (rowID + stage) % q , row_comm);
    MPI_Isend(b, n_local*n_local, MPI_DOUBLE, nbrs[UP], 111, grid_comm,&my_request1);   
    MPI_Irecv(b, n_local*n_local, MPI_DOUBLE, nbrs[DOWN], 111, grid_comm,&my_request2);                         
    MPI_Wait(&my_request1, &status);
    MPI_Wait(&my_request2, &status);
    multiplyMatrix(a_temp,b,c,n_local);
}

部分行列a_temp、b、b_tempは、チャンクn / numprocess * n / numprocessesを指すdouble型のポインターです(これは、ブロック行列のサイズです。たとえば、b =(double *)calloc(n / numprocess * n / numprocesses、sizeof (double)))。

MPI_Waitを呼び出す前にmultiplyMatrix関数を使用したいのですが(通信と計算のオーバーラップを構成します)、その方法がわかりません。2つの別々のバッファーを用意し、それらを異なる段階で交互に使用する必要がありますか?

(MPI_Sendrecv_replaceを使用できることはわかっていますが、送信と受信のブロックを使用するため、オーバーラップには役立ちません。MPI_Sendrecvについても同じことが言えます)

4

1 に答える 1

0

私は実際にこれを行う方法を考え出しました。この質問はおそらく削除する必要があります。しかし、私は MPI を初めて使用するので、これらのソリューションをここに投稿します。改善のための提案があれば、共有していただければ幸いです。方法 1:

// Fox's algorithm
 double * b_buffers[2];
 b_buffers[0] = (double *) malloc(n_local*n_local*sizeof(double));
 b_buffers[1] = b;
 for (stage =0;stage < q; stage++){
       //copying a into a_temp and Broadcasting a_temp of each proccess to all other proccess in its row
        for (i=0;i< n_local*n_local; i++)
            a_temp[i]=a[i];
        if (stage == 0) {
           MPI_Bcast(a_temp, n_local*n_local, MPI_DOUBLE, (rowID + stage) % q , row_comm);
           multiplyMatrix(a_temp,b,c,n_local);
           MPI_Isend(b, n_local*n_local, MPI_DOUBLE, nbrs[UP], 111, grid_comm,&my_request1);    
           MPI_Irecv(b, n_local*n_local, MPI_DOUBLE, nbrs[DOWN], 111, grid_comm,&my_request2);
           MPI_Wait(&my_request2, &status);
           MPI_Wait(&my_request1, &status);
      }


       if (stage > 0)
       {        
           //shifting b values in all procces
            MPI_Bcast(a_temp, n_local*n_local, MPI_DOUBLE, (rowID + stage) % q , row_comm);
            MPI_Isend(b_buffers[(stage)%2], n_local*n_local, MPI_DOUBLE, nbrs[UP], 111, grid_comm,&my_request1);    
            MPI_Irecv(b_buffers[(stage+1)%2], n_local*n_local, MPI_DOUBLE, nbrs[DOWN], 111, grid_comm,&my_request2);
                multiplyMatrix(a_temp, b_buffers[(stage)%2], c, n_local);           
            MPI_Wait(&my_request2, &status);
            MPI_Wait(&my_request1, &status);

     }      
}    

方法 2:

// Fox's algorithm

 for (stage =0;stage < q; stage++){
       //copying a into a_temp and Broadcasting a_temp of each proccess to all other proccess in its row
        for (i=0;i< n_local*n_local; i++)
            a_temp[i]=a[i];
        if (stage == 0) {
           MPI_Bcast(a_temp, n_local*n_local, MPI_DOUBLE, (rowID + stage) % q , row_comm);
           multiplyMatrix(a_temp,b,c,n_local);
           MPI_Isend(b, n_local*n_local, MPI_DOUBLE, nbrs[UP], 111, grid_comm,&my_request1);    
           MPI_Irecv(b, n_local*n_local, MPI_DOUBLE, nbrs[DOWN], 111, grid_comm,&my_request2);
           MPI_Wait(&my_request2, &status);
           MPI_Wait(&my_request1, &status);
      }


       if (stage > 0)
       {        
           //shifting b values in all proccess
            memcpy(b_temp, b, n_local*n_local*sizeof(double));
                MPI_Bcast(a_temp, n_local*n_local, MPI_DOUBLE, (rowID + stage) % q , row_comm);
            MPI_Isend(b, n_local*n_local, MPI_DOUBLE, nbrs[UP], 111, grid_comm,&my_request1);   
                MPI_Irecv(b, n_local*n_local, MPI_DOUBLE, nbrs[DOWN], 111, grid_comm,&my_request2);
                multiplyMatrix(a_temp, b_temp, c, n_local);         
               MPI_Wait(&my_request2, &status);
                MPI_Wait(&my_request1, &status);

     }  

これらはどちらも機能しているように見えますが、前述したように、私は MPI を初めて使用するので、コメントや提案があれば共有してください。

于 2013-03-19T17:43:06.147 に答える