2

そのため、C ++のMPIプロセス間で長さの異なるベクトルをコピーしようとしています。つまり、すべてのノードでベクトルを取得し、それらをノード0の新しいベクトルに連結します。

私は次のコードを持っていますが、それは私が期待したものを返さず、私を夢中にさせ、さらに問題を引き起こします。

コードは次のとおりです(省略形):

//previously summed all of numfrags to make _numFrag
//numfrags is a vector of the local sizes of _fragLoc
//_numFrag is the total of numfrags

MPI::COMM_WORLD.Barrier();
cout << _myid << "local numFrag = " << _fragLoc.size() << endl;
MPI::COMM_WORLD.Barrier();
for (unsigned i = 0; i < _fragLoc.size(); ++i)      cout << "fragloc(" << i << ") = " << _fragLoc[i] << endl;
MPI::COMM_WORLD.Barrier();

vector<int> outVector (_numFrag);
int displ[_numprocs]; 

if (_myid == 0) {
    double sum = 0;
    for (int i = 0; i < _numprocs; ++i) {
        displ[i] = sum;
        cout << _myid << " : " << i << " : " << sum << endl;
        sum += numfrags[i];
    }
}

MPI::COMM_WORLD.Barrier(); MPI::COMM_WORLD.Gatherv(&_fragLoc[0], numfrags[_myid], MPI::INT, &outVector[0], &numfrags[0], &displ[0], MPI::INT,0);

MPI::COMM_WORLD.Barrier();

if (_myid == 0) {
    cout << "X numFrag = " << _numFrag << endl;
    for (unsigned i = 0; i < _numFrag; ++i) cout << "outVector(" << i << ") = " << outVector[i] << endl;
}

簡単な例を挙げれば、4ノードの実行があります。擬似コードとしての変数入力は次のとおりです。

int _numprocs = 4;
vector<int> numfrags = {0,1,0,1};
vector<int> _fragLoc <node 0> = {};
vector<int> _fragLoc <node 1> = {12};
vector<int> _fragLoc <node 2> = {};
vector<int> _fragLoc <node 3> = {37};
int _numFrag = 2;

出力は次のとおりです。

2local numFrag = 0
3local numFrag = 1
0local numFrag = 0
1local numFrag = 1
fragloc(0) = 12
fragloc(0) = 37
0 : 0 : 0
0 : 1 : 0
0 : 2 : 1
0 : 3 : 1
0: after stage 2
X numFrag = 2
outVector(0) = 0
outVector(1) = 0

しかし、個々のfragLocがoutVectorにまとめられることを期待していましたが、これは発生していません。何かアドバイス?デバッグが完了したら、バリアをクリーンアップします。

4

1 に答える 1

4

私の知る限り、上記のコードは期待どおりに機能します。

#include <iostream>
#include <mpi.h>
#include <vector>

using namespace std;

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

    MPI::Init(argc, argv);
    int _myid = MPI::COMM_WORLD.Get_rank();
    int _numprocs = MPI::COMM_WORLD.Get_size();

    vector<int> _fragLoc;
    switch(_myid) {
        case 0: break;
        case 1: _fragLoc.push_back(12); break;
        case 2: break;
        case 3: _fragLoc.push_back(37); break;
    }

    int locNumFrag = _fragLoc.size();
    cout << _myid << "local numFrag = " << locNumFrag << endl;

    MPI::COMM_WORLD.Barrier();  // for printing

    vector<int> numfrags(_numprocs);
    MPI::COMM_WORLD.Allgather(&locNumFrag, 1, MPI::INT, &numfrags[0], 1, MPI::INT);

    int _numFrag = 0;
    for (int i=0; i<_numprocs; i++) 
        _numFrag += numfrags[i];

    for (unsigned i = 0; i < _fragLoc.size(); ++i)
        cout << "fragloc(" << i << ") = " << _fragLoc[i] << endl;

    MPI::COMM_WORLD.Barrier(); // for printing

    vector<int> outVector (_numFrag);
    int displ[_numprocs]; 

    if (_myid == 0) {
        double sum = 0;
        for (int i = 0; i < _numprocs; ++i) {
            displ[i] = sum;
            cout << _myid << " : " << i << " : " << sum << endl;
            sum += numfrags[i];
        }
    }

    MPI::COMM_WORLD.Gatherv(&_fragLoc[0], numfrags[_myid], MPI::INT, &outVector[0], &numfrags[0], &displ[0], MPI::INT,0);

    if (_myid == 0) {
        cout << "X numFrag = " << _numFrag << endl;
        for (unsigned i = 0; i < _numFrag; ++i) cout << "outVector(" << i << ") = " << outVector[i] << endl;
    }

    MPI::Finalize();
    return 0;
}

実行すると

$ mpirun -np 4 ./gatherv
0local numFrag = 0
1local numFrag = 1
fragloc(0) = 12
2local numFrag = 0
3local numFrag = 1
fragloc(0) = 37
0 : 0 : 0
0 : 1 : 0
0 : 2 : 1
0 : 3 : 1
X numFrag = 2
outVector(0) = 12
outVector(1) = 37
于 2013-01-29T23:26:45.053 に答える