1

MPI を理解するのに役立つように、以下の C アプリケーションを作成し、巨大な C++ アプリケーションで MPI_Barrier() が機能しない理由を説明します。ただし、はるかに小さな C アプリケーションを使用して、巨大なアプリケーションで問題を再現することができました。基本的に、for ループ内で MPI_Barrier() を呼び出します。MPI_Barrier() はすべてのノードに表示されますが、ループを 2 回繰り返した後、プログラムはデッドロック状態になります。何かご意見は?

#include <mpi.h>
#include <stdio.h>
int main(int argc, char* argv[]) {
    MPI_Init(&argc, &argv);
    int i=0, numprocs, rank, namelen;
    char processor_name[MPI_MAX_PROCESSOR_NAME];
    MPI_Comm_size(MPI_COMM_WORLD, &numprocs);
    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
    MPI_Get_processor_name(processor_name, &namelen);
    printf("%s: Rank %d of %d\n", processor_name, rank, numprocs);
    for(i=1; i <= 100; i++) {
            if (rank==0) printf("Before barrier (%d:%s)\n",i,processor_name);
            MPI_Barrier(MPI_COMM_WORLD);
            if (rank==0) printf("After barrier (%d:%s)\n",i,processor_name);
    }

    MPI_Finalize();
    return 0;
}

出力:

alienone: Rank 1 of 4
alienfive: Rank 3 of 4
alienfour: Rank 2 of 4
alientwo: Rank 0 of 4
Before barrier (1:alientwo)
After barrier (1:alientwo)
Before barrier (2:alientwo)
After barrier (2:alientwo)
Before barrier (3:alientwo)

Ubuntu 10.10 リポジトリから GCC 4.4、Open MPI 1.3 を使用しています。

また、私の巨大な C++ アプリケーションでは、MPI ブロードキャストが機能しません。ノードの半分だけがブロードキャストを受信し、残りはそれを待ってスタックします。

助けや洞察を事前にありがとう!

更新: Open MPI 1.4.4 にアップグレードされ、ソースから/usr/local/にコンパイルされました。

更新:実行中のプロセスに GDB をアタッチすると、興味深い結果が得られます。MPI システムがバリアで停止したように見えますが、MPI はまだプログラムが実行されていると考えています。

GDB をアタッチすると、興味深い結果が得られます。すべてのノードが MPI バリアで停止しているように見えますが、MPI はまだそれらが実行されていると考えています。

0x00007fc235cbd1c8 in __poll (fds=0x15ee360, nfds=8, timeout=<value optimized out>) at   ../sysdeps/unix/sysv/linux/poll.c:83
83  ../sysdeps/unix/sysv/linux/poll.c: No such file or directory.
    in ../sysdeps/unix/sysv/linux/poll.c
(gdb) bt
#0  0x00007fc235cbd1c8 in __poll (fds=0x15ee360, nfds=8, timeout=<value optimized out>) at ../sysdeps/unix/sysv/linux/poll.c:83
#1  0x00007fc236a45141 in poll_dispatch () from /usr/local/lib/libopen-pal.so.0
#2  0x00007fc236a43f89 in opal_event_base_loop () from /usr/local/lib/libopen-pal.so.0
#3  0x00007fc236a38119 in opal_progress () from /usr/local/lib/libopen-pal.so.0
#4  0x00007fc236eff525 in ompi_request_default_wait_all () from /usr/local/lib/libmpi.so.0
#5  0x00007fc23141ad76 in ompi_coll_tuned_sendrecv_actual () from /usr/local/lib/openmpi/mca_coll_tuned.so
#6  0x00007fc2314247ce in ompi_coll_tuned_barrier_intra_recursivedoubling () from /usr/local/lib/openmpi/mca_coll_tuned.so
#7  0x00007fc236f15f12 in PMPI_Barrier () from /usr/local/lib/libmpi.so.0
#8  0x0000000000400b32 in main (argc=1, argv=0x7fff5883da58) at barrier_test.c:14
(gdb) 

更新:私もこのコードを持っています:

#include <mpi.h>
#include <stdio.h>
#include <math.h>
int main( int argc, char *argv[] )  {
int n = 400, myid, numprocs, i;
double PI25DT = 3.141592653589793238462643;
double mypi, pi, h, sum, x;
MPI_Init(&argc,&argv);
MPI_Comm_size(MPI_COMM_WORLD,&numprocs);
MPI_Comm_rank(MPI_COMM_WORLD,&myid);
printf("MPI Rank %i of %i.\n", myid, numprocs);
while (1) {
    h   = 1.0 / (double) n;
    sum = 0.0;
    for (i = myid + 1; i <= n; i += numprocs) {
        x = h * ((double)i - 0.5);
        sum += (4.0 / (1.0 + x*x));
    }
    mypi = h * sum;
    MPI_Reduce(&mypi, &pi, 1, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD);
    if (myid == 0)
        printf("pi is approximately %.16f, Error is %.16f\n",  pi, fabs(pi - PI25DT));
}
MPI_Finalize();
return 0;
}

無限ループにもかかわらず、ループ内の printf() からの出力は 1 つだけです。

mpirun -n 24 --machinefile /etc/machines a.out 
MPI Rank 0 of 24.
MPI Rank 3 of 24.
MPI Rank 1 of 24.
MPI Rank 4 of 24.
MPI Rank 17 of 24.
MPI Rank 15 of 24.
MPI Rank 5 of 24.
MPI Rank 7 of 24.
MPI Rank 16 of 24.
MPI Rank 2 of 24.
MPI Rank 11 of 24.
MPI Rank 9 of 24.
MPI Rank 8 of 24.
MPI Rank 20 of 24.
MPI Rank 23 of 24.
MPI Rank 19 of 24.
MPI Rank 12 of 24.
MPI Rank 13 of 24.
MPI Rank 21 of 24.
MPI Rank 6 of 24.
MPI Rank 10 of 24.
MPI Rank 18 of 24.
MPI Rank 22 of 24.
MPI Rank 14 of 24.
pi is approximately 3.1415931744231269, Error is 0.0000005208333338

何かご意見は?

4

2 に答える 2

2

OpenMPI の MPI_Barrier() は、プロセスが最後のバリアの後に渡されたさまざまな時間にバリアに遭遇するとハングすることがありますが、私が見ることができるように、それはあなたのケースではありません。とにかく、代わりに、または MPI_Barrier() を実際に呼び出す前に、MPI_Reduce() を使用してみてください。これはバリアと直接同等ではありませんが、コミュニケーター内のすべてのプロセスを含むペイロードがほとんどない同期呼び出しは、バリアのように機能するはずです。LAM/MPI、MPICH2、さらには WMPI で MPI_Barrier() のそのような動作を見たことはありませんが、OpenMPI では実際の問題でした。

于 2012-03-25T07:42:57.123 に答える
1

どの相互接続がありますか? InfiniBand や Myrinet のような特殊なものですか、それとも単純な TCP over Ethernet を使用しているだけですか? TCP トランスポートで実行している場合、複数のネットワーク インターフェイスが構成されていますか?

さらに、Open MPI はモジュール式です。さまざまな集合操作を実装するアルゴリズムを提供する多くのモジュールがあります。MCA パラメーターを使用してそれらをいじることができます。たとえばmpirun--mca btl_base_verbose 30. 次のようなものを探します。

[node1:19454] btl: tcp: attempting to connect() to address 192.168.2.2 on port 260
[node2:29800] btl: tcp: attempting to connect() to address 192.168.2.1 on port 260
[node1:19454] btl: tcp: attempting to connect() to address 192.168.109.1 on port 260
[node1][[54886,1],0][btl_tcp_endpoint.c:638:mca_btl_tcp_endpoint_complete_connect] connect() to 192.168.109.1 failed: Connection timed out (110)

その場合、一部 (またはすべて) のノードには複数の構成済みネットワーク インターフェイスが設定されていますが、すべてのノードがすべてのインターフェイスを介して到達できるわけではありません。これは、ノードがデフォルトごとに Xen サポート (RHEL?) を有効にした最新の Linux ディストリビューションを実行している場合、または仮想ネットワーク インターフェイスを起動する他の仮想化ソフトウェアがノードにインストールされている場合に発生する可能性があります。

デフォルトでは、Open MPI はレイジーです。つまり、connectinos はオンデマンドで開かれます。最初の送受信通信は、適切なインターフェイスが選択された場合に成功する可能性がありますが、後続の操作では、帯域幅を最大化するために代替パスの 1 つが選択される可能性があります。2 番目のインターフェイスを介して他のノードに到達できない場合、タイムアウトが発生する可能性が高く、Open MPI が他のノードがダウンしているか問題があると見なすため、通信が失敗します。

btl解決策は、TCPモジュールの MCA パラメータを使用して、接続していないネットワークまたはネットワーク インターフェイスを分離することです。

  • 通信に特定の IP ネットワークのみを使用するように Open MPI を強制します。--mca btl_tcp_if_include 192.168.2.0/24
  • 完全なネットワーク接続を提供することが知られているネットワーク インターフェイスの一部のみを使用するように Open MPI を強制します。--mca btl_tcp_if_include eth0,eth1
  • Open MPI に、プライベート/仮想であることがわかっている、またはノードに接続していない他のネットワークに属していることがわかっているネットワーク インターフェイスを使用しないように強制します (そうする場合は、 loopback を除外する必要loがあります)。--mca btl_tcp_if_exclude lo,virt0

詳細については、Open MPI ランタイム TCP チューニング FAQを参照してください。

于 2012-05-04T11:08:44.837 に答える