2010-12-14 4 views
1

を送信し、私は次のアルゴリズムを実装するためにオープンMPIライブラリを使用しています:私たちは、2つのプロセスp1p2を持っています。彼らは両方ともいくつかの反復を実行しており、各反復の最後に結果を伝えます。 、私はp1によって実行された最後の反復からの最新の結果を読み取るためにp2をしたい問題は、実行が必ずしもバランスがとれていないということですので、p1p2は、たとえ1実行時間に10回の反復を実行することができます。MPI:非ブロックをキャンセルする

このように、私の考えはp1が各繰り返しでその結果を送信していることです。しかし、反復の結果をiに送信する前に、p2が実際に反復i-1の情報を読み取るかどうかを確認する必要があります。そうでない場合、それはp2p1から読み込むとき、それは最新の結果を読み込みますようにを送る前のをキャンセルする必要があります。

残念ながら、私はそれを行うするかどうかはわかりません。それは私が好きな送信がキャンセルとp2印刷物1の代わりに、2

することができなかったことを言って、

int main (int argc, char *argv[]){ 

    int myrank, numprocs; 
    MPI_Status status; 
    MPI_Request request; 

    MPI_Init(&argc, &argv); 
    MPI_Comm_size(MPI_COMM_WORLD, &numprocs); 
    MPI_Comm_rank(MPI_COMM_WORLD, &myrank); 

    if(myrank == 0){ 
     int send_buf = 1, flag; 
     MPI_Isend(&send_buf, 1, MPI_INT, 1, 123, MPI_COMM_WORLD, 
        &request); 
     MPI_Cancel(&request); 
     MPI_Wait(&request, &status); 
     MPI_Test_cancelled(&status, &flag); 
     if (flag) printf("Send cancelled\n"); 
     else printf("Send NOT cancelled\n"); 
     send_buf = 2; 
     MPI_Isend(&send_buf, 1, MPI_INT, 1, 123, MPI_COMM_WORLD, 
        &request); 
    } 
    else { 
     sleep(5); 
     int msg; 
     MPI_Recv(&msg, 1, MPI_INT, 0, 123, 
       MPI_COMM_WORLD, &status); 
     printf("%d\n", msg); 
    } 
    MPI_Finalize(); 

    return 0; 
} 

しかし、私は実行すると:私は、次のコードのように、MPI_Cancelを使用して試してみました私が提案していることを達成するための方法があるかどうか、あるいは行動をコード化するための代替方法がp1p2の間にあるかどうかを知るためです。

+0

送信キャンセル悪であり、あなたがそれを使用するべきではありません。実際に送信をキャンセルできる保証はありません。もし、あなたが義務をキャンセルして遠隔で書くことを防ぐことができれば、あなたは失望します。 – Jeff

答えて

5

私は通信の制御をやり直すでしょう。 p1の代わりに、キャンセルする必要がある不要なメッセージを送信すると、p2はメッセージを受信する準備ができていることを通知し、p1はそれだけを送信します。その間、p1は送信バッファを最新の結果で単に上書きします。

で(未テスト)コード:私が言ったように

if (rank == 0) 
{ 
    int ready; 
    MPI_Request p2_request; 
    MPI_Status p2_status; 
    // initial request 
    MPI_Irecv(&ready, 1, MPI_INT, 1, 123, MPI_COMM_WORLD, &p2_request); 
    for (int i=0; true; i++) 
    { 
     sleep(1); 
     MPI_Test(&p2_request, &ready, &p2_status); 
     if (ready) 
     { 
      // blocking send: p2 is ready to receive 
      MPI_Send(&i, 1, MPI_INT, 1, 123, MPI_COMM_WORLD); 
      // post new request 
      MPI_Irecv(&ready, 1, MPI_INT, 1, 123, MPI_COMM_WORLD, &p2_request); 
     } 
    } 
} 
else 
{ 
    int msg; 
    MPI_Status status; 
    while (true) 
    { 
     sleep(5); 
     // actual message content doesn't matter, just let p1 know we're ready 
     MPI_Send(&msg, 1, MPI_INT, 0, 123, MPI_COMM_WORLD); 
     // receive message 
     MPI_Recv(&msg, 1, MPI_INT, 0, 123, MPI_COMM_WORLD, &status); 
    } 
} 

は今、それがテストされていないコードですが、あなたはおそらく、私はそこに取得していますかを見ることができます。 MPI_Cancelは、状況がひどく間違っている場合にのみ使用してください。通常の実行中にメッセージをキャンセルする必要はありません。

5

別のアプローチは、完全にMPI片側通信を使用することであろう(例えば、http://www.linux-mag.com/id/1793)。しかし、あなたが本当に望んでいるパッシブ通信を行うことはかなり難しいです(mpi_win_postとmpi_win_startを使ってペアごとには簡単ですが)一方的なものはうまくいけばMPI-3のすべてが変わるので、私はあなたに行くことをアドバイスしたいと思っています。

メッセージをキャンセルするのではなく、メッセージを取り消すのではなく、ここで試したことに直接関係しています(上記のようにかなり劇的です)。互いを追い越す - あなたはMPI_THREAD_MULTIPLEを使用し、注文がporly定義されている場合には1つのMPIタスク内の送信複数のスレッドがある場合のみの注意点は)次のとおりです。

#include <stdio.h> 
#include <mpi.h> 
#include <stdlib.h> 
#include <unistd.h> 
#include <math.h> 

void compute() { 
    const int maxusecs=500; 
    unsigned long sleepytime=(unsigned long)round(((float)rand()/RAND_MAX)*maxusecs); 

    usleep(sleepytime); 
} 

int main(int argc, char** argv) 
{ 
    int rank, size, i; 
    int otherrank; 
    const int niters=10; 
    const int tag=5; 
    double newval; 
    double sentvals[niters+1]; 
    double othernewval; 
    MPI_Request reqs[niters+1]; 
    MPI_Status stat; 
    int ready; 

    MPI_Init(&argc, &argv); 
    MPI_Comm_rank(MPI_COMM_WORLD, &rank); 
    MPI_Comm_size(MPI_COMM_WORLD, &size); 
    if (size != 2) { 
    fprintf(stderr,"This assumes 2 processes\n"); 
    MPI_Finalize(); 
    exit(-1); 
    } 

    otherrank = (rank == 0 ? 1 : 0); 
    srand(rank); 

    compute(); 
    newval = rank * 100. + 0; 
    sentvals[0] = newval; 
    MPI_Isend(&(sentvals[0]), 1, MPI_DOUBLE, otherrank, tag, MPI_COMM_WORLD, &(reqs[0])); 
    MPI_Recv (&othernewval, 1, MPI_DOUBLE, otherrank, tag, MPI_COMM_WORLD, &stat); 
    for (i=0; i<niters; i++) { 

     MPI_Iprobe(otherrank, tag, MPI_COMM_WORLD, &ready, &stat); 
     while (ready) { 
      MPI_Recv(&othernewval, 1, MPI_DOUBLE, otherrank, tag, MPI_COMM_WORLD, &stat); 
      printf("%s[%d]: Reading queued data %lf:\n", 
        (rank == 0 ? "" : "\t\t\t\t"), rank, othernewval); 
      MPI_Iprobe(otherrank, tag, MPI_COMM_WORLD, &ready, &stat); 
     } 

     printf("%s[%d]: Got data %lf, computing:\n", 
       (rank == 0 ? "" : "\t\t\t\t"), rank, othernewval); 
     compute(); 

     /* update my data */ 
     newval = rank * 100. + i + 1; 
     printf("%s[%d]: computed %lf, sending:\n", 
       (rank == 0 ? "" : "\t\t\t\t"), rank, newval); 
     sentvals[i+1] = newval; 
     MPI_Isend(&(sentvals[i+1]), 1, MPI_DOUBLE, otherrank, tag, MPI_COMM_WORLD, &(reqs[0])); 
    } 


    MPI_Finalize(); 

    return 0; 
} 

は、データが送信されるという理由だけで、この(あなたに与えられる通知を実行します印刷時に受け取ったものではありません):

[0]: Got data 100.000000, computing: 
           [1]: Got data 0.000000, computing: 
[0]: computed 1.000000, sending: 
[0]: Got data 100.000000, computing: 
           [1]: computed 101.000000, sending: 
           [1]: Got data 0.000000, computing: 
[0]: computed 2.000000, sending: 
[0]: Got data 100.000000, computing: 
           [1]: computed 102.000000, sending: 
           [1]: Reading queued data 1.000000: 
           [1]: Got data 1.000000, computing: 
[0]: computed 3.000000, sending: 
[0]: Reading queued data 101.000000: 
[0]: Got data 101.000000, computing: 
           [1]: computed 103.000000, sending: 
           [1]: Reading queued data 2.000000: 
           [1]: Got data 2.000000, computing: 
[0]: computed 4.000000, sending: 
           [1]: computed 104.000000, sending: 
[0]: Reading queued data 102.000000: 
           [1]: Reading queued data 3.000000: 
           [1]: Got data 3.000000, computing: 
[0]: Got data 102.000000, computing: 
[0]: computed 5.000000, sending: 
[0]: Reading queued data 103.000000: 
[0]: Got data 103.000000, computing: 
           [1]: computed 105.000000, sending: 
           [1]: Reading queued data 4.000000: 
           [1]: Got data 4.000000, computing: 
[0]: computed 6.000000, sending: 
[0]: Reading queued data 104.000000: 
[0]: Got data 104.000000, computing: 
           [1]: computed 106.000000, sending: 
           [1]: Reading queued data 5.000000: 
           [1]: Got data 5.000000, computing: 
[0]: computed 7.000000, sending: 
[0]: Reading queued data 105.000000: 
[0]: Got data 105.000000, computing: 
           [1]: computed 107.000000, sending: 
           [1]: Reading queued data 6.000000: 
           [1]: Got data 6.000000, computing: 
[0]: computed 8.000000, sending: 
[0]: Reading queued data 106.000000: 
[0]: Got data 106.000000, computing: 
           [1]: computed 108.000000, sending: 
           [1]: Reading queued data 7.000000: 
           [1]: Got data 7.000000, computing: 
[0]: computed 9.000000, sending: 
[0]: Reading queued data 107.000000: 
[0]: Got data 107.000000, computing: 
           [1]: computed 109.000000, sending: 
           [1]: Reading queued data 8.000000: 
           [1]: Got data 8.000000, computing: 
[0]: computed 10.000000, sending: 
           [1]: computed 110.000000, sending: 

これは単なるデモコードであることに注意し、最終版本当にが保留中の要求を解放し、待機中のメッセージを消去するためにそこに終わりwaitalls、よりiprobesを行う必要があります。

0

環境とMPIディストリビューションはマルチスレッドをサポートしていますか?もしそうなら、あなたはP1のメインスレッドと共有変数に値を格納し、各反復の結果を算出し、P1内のスレッドを作成することができます(書き込みはセマフォを経由して保護された) 上記suszterpattによって示唆されるように、その後、P2は、「私は準備ができてい送ってきました"メッセージをP1に送信し、P1に最新の反復からの値を応答させる。

関連する問題