C ++:使用MPI的gatherv来连接不同长度的向量 [英] C++: Using MPI's gatherv to concatenate vectors of differing lengths

查看:153
本文介绍了C ++:使用MPI的gatherv来连接不同长度的向量的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

因此我试图在C ++中的MPI进程之间复制不同长度的向量,即在所有节点上获取向量并将它们连接到节点0上的新向量。



我有以下代码,它不会返回我的预期,驱使我疯狂,并进一步下降线。



代码是这里(缩写):

  //预先汇总所有numfrags以使_numFrag 
// numfrags是局部大小_fragLoc
// _ numFrag是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] 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;
}

举一个简单的例子,我有一个四节点运行。这里是作为伪代码的变量输入:

  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:
X numFrag = 2
outVector(0)= 0
outVector(1)= 0

但我预计个人fragLoc的一起放在outVector,这不会发生。任何建议?当我完成调试时,我会清除障碍。

解决方案

据我所知,如预期。

  #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);打破;
case 2:break;
case 3:_fragLoc.push_back(37);打破;
}

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 $ b b 0:3:1
X numFrag = 2
outVector(0)= 12
outVector(1)= 37


so I'm trying to copy over vectors of different lengths between MPI processes in C++, namely taking vectors on all of the nodes and concatenating them into a new vector on node 0.

I have the following code, which does not return what I expected, driving me crazy, and causing trouble further down the line.

The code is this (abbreviated):

//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;
}

Giving a simple example, I have a four-node run. Here are the variable inputs as pseudocode:

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;

The output is:

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

But I expected the individual fragLoc's to be put together into outVector and this isn't happening. Any advice? I'll clean up the barriers when I'm done debugging.

解决方案

As far as I can tell, the code above works as expected.

#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;
}

Running gives

$ 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

这篇关于C ++:使用MPI的gatherv来连接不同长度的向量的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆