2

MPI経由で関数ポインタを渡すことは、他のノードに関数呼び出しを指示する方法として安全ですか?誰かが、MPIを介してあらゆる種類のポインタを渡すことは無意味だと言うかもしれませんが、私はそれを検証するためのコードを書きました。ここでMPI経由で関数ポインタを送信

//test.cpp 
#include <cstdio> 
#include <iostream> 
#include <mpi.h> 
#include <cstring> 

using namespace std; 

int f1(int a){return a + 1;} 
int f2(int a){return a + 2;} 
int f3(int a){return a + 3;} 

using F=int (*)(int); 

int main(int argc, char *argv[]){ 
    MPI_Init(&argc, &argv); 
    int rank, size; 
    MPI_Status state; 
    MPI_Comm_size(MPI_COMM_WORLD, &size); 
    MPI_Comm_rank(MPI_COMM_WORLD, &rank); 

    //test 
    char data[10]; 
    if(0 == rank){ 
     *(reinterpret_cast<F*>(data))=&f2; 
     for(int i = 1 ; i < size ; ++i) 
      MPI_Send(data, 8, MPI_CHAR, i, 0, MPI_COMM_WORLD); 
    }else{ 
     MPI_Recv(data, 8, MPI_CHAR, 0, 0, MPI_COMM_WORLD, &state); 
     F* fp = reinterpret_cast<F*>(data); 
     int ans = (**fp)(10); 
     cout << ans << endl; 
    } 


    MPI_Finalize(); 
    return 0; 
} 

が出力されます。

12 
12 
12 
12 
12 
12 
12 
12 
12 

私はMVAPICHを経由して、それを実行し、それがうまく動作します。 しかし私はちょうど別のアドレス空間は、ポインタ値がそれを生成したプロセス以外のプロセスでUSELESSであることを意味するので、なぜ今はしません。

P.S.ここに私のホストファイルは

blade11:1 
blade12:1 
blade13:1 
blade14:1 
blade15:1 
blade16:1 
blade17:1 
blade18:2 
blade19:1 

であり、私はそれはあなたがあなたのクラスタ環境が均質であり、通常の実行ファイルには、アドレス空間のランダム化がでていないという意味で幸運ですC++ 11

答えて

7

を使用してmpiexec -n 10 -f hostfile ./testを走り、コンパイル場所。結果として、すべてのイメージは同じベースアドレスにロードされ、メモリ内に同様に配置されます。したがって、関数はすべてのMPIランクで同じ仮想アドレスを持ちます(ダイナミックリンクされたライブラリのシンボルではほとんどありませんランダムアドレス)。

異なるコンパイラを使用して、または同じコンパイラを使用していて異なるコンパイラオプションを使用してソースを2回コンパイルすると、最初の実行可能ファイルを実行して残りのファイルを実行すると、プログラムが確実にクラッシュします。 test_O0test_O2に異なるサイズの関数コード内の最適化結果の

$ mpicxx -std=c++11 -O0 -o test_O0 test.cpp 
$ mpicxx -std=c++11 -O2 -o test_O2 test.cpp 
$ mpiexec -f hostfile -n 5 ./test_O0 : -n 5 ./test_O2 
12 
12 
12 
12 
<crash> 

異なるレベル:

はこれを試してみてください。したがって、f2は、すべてのランク内で同じ仮想アドレスを持つことはもはやありません。ランク0と同じ実行可能ファイルを実行するランクは12を出力し、残りはsegfaultを出力します。

2

他のノードに関数を呼び出す方法としてMPI経由で関数ポインタを渡すことは安全ですか?

いいえ、そうではありません。アドレス空間はプロセス間で共有されません。

しかし、同じソースから構築されたプログラムの結果であるMPIプロセスは、特定のメッセージを受信したときに特定の機能を呼び出すように編成することができる。

char data = 0; 
MPI_Recv(data, 1, MPI_CHAR, 0, 0, MPI_COMM_WORLD, &state); 

if (data == 255) { 
    f2(10); /* and so forth */ 
} 
0

があります関数の特定のコード化を、すべてのプロセスで一意に認識できるローカル関数ポインタ/コールバックにマップするマクロを含むトリックです。 たとえば、HPX http://stellar.cct.lsu.edu/files/hpx_0.9.5/html/HPX_PLAIN_ACTION.htmlでは、不均一なシステム間で機能を実行するために使用されます。

関連する問題