1

「-np 2」で mpirun を呼び出します。ランク0のプロセスを「マスター」、ランク1のプロセスを「スレーブ」と呼んでいます。

ゴール:

  1. マスターは時々 のようなメッセージをスレーブに送信しますmpi::send(1, UPDATE, data);。他のメッセージ タイプには、DIE、COMPUTE などがあります。これらのメッセージ タイプは、一意の値を持つ定数の整数です。
  2. スレーブは無限ループを実行し、マスターからのメッセージを「リッスン」します。メッセージを受信すると、受信確認をマスターに送り返します。

実装:

スレーブ実行:

...
int updateData, computeData;
mpi::request updateRequest = world.irecv(0,UPDATE, updateData);    
mpi::request computeRequest = world.irecv(0,COMPUTE, computeData);    

do {
  cerr << "slave ready to take a command" << endl;
  if(updateRequest.test()) {
    cerr << "slave ireceived UPDATE" << endl;
    world.send(0, UPDATE_ACK, 0);
    cerr << "slave sent UPDATE_ACK" << endl;

    /* do something useful 
    ...
    ...
    */

    updateRequest = world.irecv(0, UPDATE, updateData);

  } else if (computeRequest.test()) {
    ...
  } else {
    boost::this_thread::sleep( boost::posix_time::seconds(1) );
  }
}

マスターが実行されている間:

...
world.send(1, UPDATE, 10);
cerr << "master sent UPDATE" << endl;
int dummy;
world.recv(1, UPDATE_ACK, dummy);
cerr << "master received UPDATE_ACK" << endl;
...  

マスターのコードのより多くのコンテキスト:

...
// update1
world.send(1, UPDATE, params);
cerr << "master sent UPDATE" << endl;
int dummy;
world.recv(1, UPDATE_ACK, dummy);
cerr << "master received UPDATE_ACK" << endl;

// update2
world.send(1, UPDATE2, params2);
cerr << "master sent UPDATE2" << endl;
world.recv(1, UPDATE2_ACK, dummy);
cerr << "master received UPDATE2_ACK" << endl;

// update3
world.send(1, UPDATE3, params3);
cerr << "master sent UPDATE3" << endl;
world.recv(1, UPDATE3_ACK, dummy);
cerr << "master received UPDATE3_ACK" << endl;

...

// training iterations
do {
  
  mpi::request computeRecvReq1, computeRecvReq2;
  std::map<int, int> result1, result2;

  // for each line in a text file, the master asks the slave(s)
  // to compute two things and aggregates the results
  for(unsigned sentId = 0; sentId != data.size(); sentId++) {

    // these two functions won't return until at least one slave is "idle"
    CollectSlavesWork1(computeRecvReq1, result1);
    CollectSlavesWork2(computeRecvReq2, result2);

    // async ask the slave to compute and async get the results
    world.isend(1, COMPUTE, sentId);
    computeRecvReq1 = world.irecv(1, RESULT1, result1);
    computeRecvReq2 = world.irecv(1, RESULT2, result2);

  }

  // based on the slave(s) work, the master updates params1 
  // and send them again to the slave(s)
  world.send(1, UPDATE, params);
  cerr << "master sent UPDATE" << endl;
  world.recv(1, UPDATE_ACK, dummy);              // PROBLEM HAPPENS HERE
  cerr << "master received UPDATE_ACK" << endl;


} while(!ModelIsConverged())

...  

出力:

...

コマンドを取る準備ができているスレーブ

マスターが更新を送信しました

スレーブ ireceived UPDATE

スレーブは UPDATE_ACK を送信しました

マスターが UPDATE_ACK を受信しました

コマンドを取る準備ができているスレーブ

...

コマンドを取る準備ができているスレーブ

マスターが更新を送信しました

スレーブ ireceived UPDATE

スレーブは UPDATE_ACK を送信しました

コマンドを取る準備ができているスレーブ

...

問題: マスターが初めて UPDATE メッセージを送信したとき、すべて問題ないように見えます。ただし、2 回目では、マスターは UPDATE_ACK を受信しません。

4

0 に答える 0