0

ここで同じ質問をしましたが、長すぎたと思うので、もっと短い方法で再試行します。

マスター/スレーブ設定のRocksクラスターで最新のOpenMPIを使用するC++プログラムがあります。スレーブはタスクを実行してから、ブロッキングMPI_SEND / MPI_RECV呼び出し(Boost MPIを介して)を使用してマスターにデータを報告します。これにより、データがデータベースに書き込まれます。現在、マスターはスレーブよりも大幅に低速です。スレーブの約半分が最初のタスクでスタックし、データを報告しないため、プログラムに問題があります。strace / ltraceを使用すると、MPI_SENDでのポーリングが停止し、メッセージが受信されないようです。

私はこの理論をテストするプログラムを作成しました(ここでも完全にリストされています)。スリープを使用してスレーブとマスターの速度を操作することにより、同様の問題を引き起こす可能性があります。speed(master)> speed(slaves)の場合、すべてが正常に機能します。speed(master)<speed(slaves)の場合、一部のスレーブでは毎回メッセージが大幅に遅延します。

なぜこれが起こるのか、何か考えはありますか?

4

1 に答える 1

1

私が見る限り、これはマスターノードのwhileループのrecvに起因します。

 ...
 while (1) {
 // Receive results from slave.
      stat = world.recv(MPI_ANY_SOURCE,MPI_ANY_TAG);
 ...

1つのスレーブからのメッセージがある場合、マスターノードは並列で実行されていないため、whileループ内のコードが終了するまで(スリープがあるため、しばらく時間がかかります)、マスターはメッセージを取得できません。したがって、他のすべてのスレーブは、最初のスレーブがメッセージの送信を終了するまで、メッセージの送信を開始できません。次に、次のスレーブはメッセージの送信を開始できますが、whileループ内のコードが実行されるまで、他のすべてのスレーブは停止されます。

これにより、スレーブの通信が非常に遅いという動作が発生します。この問題を回避するには、ポイントツーポイント通信をノンブロッキングで実装するか、グローバル通信を使用する必要があります。

更新1:

マスターが自分のデータを配布したと仮定しましょう。今、彼は奴隷が報告するまで待ちます。最初のスレーブが報告すると、最初にREPORTTAGを送信し、次にDONETAGを送信します。今、マスターは彼に新しい仕事を送り返します

 currentTask < numtasks

今、奴隷は彼の計算から再び始めます。彼が終了するまで、マスターは別のスレーブしか処理できなかったのかもしれません。したがって、最初のスレーブは、最初にREPORTTAGを送信し、次にDONETAGを送信して、新しいジョブを取得します。これが最終的に続くとき、2人の奴隷だけが新しい仕事を得て、残りは彼らの仕事を終えることができませんでした。したがって、ある時点でこれは真実です。

 currentTask >= numtasks

これで、すべてのスレーブがデータを報告し、複数のタスクを実行したわけではなくても、すべてのジョブを停止できます。

この問題は、異なるノードのネットワーク接続が大きく異なる場合に最も発生します。その理由は、送信と受信は呼び出し後に処理されず、代わりに、これらの機能の2つが何らかのハンドシェイクを実行できる場合に通信が行われるためです。

解決策として、私は次のいずれかを提案します:

  • すべてのジョブを強制終了する前に、すべてのスレーブが終了していることを確認してください
  • メッセージの代わりに収集と分散を使用すると、各タスクの後にすべてのスレーブが同期されます。
  • メッセージがそれほど大きくない場合は、バッファリングされた、またはバッファリングされていない送信および受信操作を使用します。マスターでメモリオーバーフローが発生していないことを確認してください
  • マスター/スレーブからより並列なワークモードに変更します。たとえば、すべてのタスクを2つのノードに分割し、次にこれらのノードから次の2つのノードにタスクをさらに分割します。最後に、この方法でタスクを送り返します。このソリューションには、通信コストがO(n)ではなくO(logn)のみであるという利点もあります。

これがお役に立てば幸いです。

于 2011-10-20T01:02:39.523 に答える