使用 MPI 分散对的 c++ 向量

Scatter a c++ vector of pairs with MPI

本文关键字:c++ 向量 MPI 分散 使用      更新时间:2023-10-16

我是MPI的新手,所以我正在寻求你的帮助。我需要使用 MPI C++分散一个对向量。为此,我创建了一个MPI_Datatype"mytype"。然后我使用MPI_Scatterv因为我不希望散点依赖于向量的大小,也不依赖于进程的数量。

这是我的代码:

#include<mpi.h>
#include<iostream>
#include<vector>
using std::cout;
using std::cerr;
using std::endl;
using std::vector;
using std::pair;
typedef vector<pair< int, int> > Vect;

void Build_mpi_type(unsigned int* i, unsigned int* j, MPI_Datatype* mytype)
{
    int array_of_blocklengths[2]={1,1};
    MPI_Datatype array_of_types[2]={MPI_INT, MPI_INT};
    MPI_Aint i_addr, j_addr;
    MPI_Aint array_of_displacements[2]={0};
    MPI_Get_address(i,&i_addr);
    MPI_Get_address(j,&j_addr);
    array_of_displacements[1]=j_addr-i_addr;
    MPI_Type_create_struct(2,array_of_blocklengths,array_of_displacements,array_of_types,mytype);
    MPI_Type_commit(mytype);
}

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

    Vect esempio;
    esempio.push_back(std::make_pair(1,1));
    esempio.push_back(std::make_pair(2,2));
    esempio.push_back(std::make_pair(3,3));
    esempio.push_back(std::make_pair(4,4));
    unsigned int size=esempio.size();

    MPI_Init(&argc, &argv);
    int rank;
    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
    int p;
    MPI_Comm_size(MPI_COMM_WORLD, &p);

    unsigned int* index_i=nullptr;
    unsigned int* index_j=nullptr;
    MPI_Datatype mytype;
    Build_mpi_type(index_i, index_j,&mytype);

    //cout<<esempio.size();
    vector<int> elem(p); //number of elements per process
    vector<int> disp(p); // first index for every local vector
    // how to distribute elements
    int split = size / p;
    int extra = size % p;
    for (int i = 0; i < extra; ++i) 
            elem[i] = split + 1;
    for (int i = extra; i < p; ++i) 
            elem[i] = split;
    for (int i = 1; i < p; ++i) 
            disp[i] = disp[i-1] + elem[i-1];
    int local_n = elem[rank]; 
    Vect local_v(local_n); 

    MPI_Scatterv(&esempio[0], &elem[0], &disp[0], mytype,
                 &local_v[0], local_n, mytype,
                 0, MPI_COMM_WORLD);
       if(rank==0){
               for(Vect::const_iterator pos = local_v.begin();pos != local_v.end(); ++pos)
cout<<pos->first<<" "<<pos->second<<endl;
    }
    MPI_Finalize();
    return 0;
}

现在的问题是,当我只用一个进程(根)运行程序时,我会得到这个结果:

1 1
2 2
0 0
0 0

当我使用两个和三个进程运行时,我有:

1 1
0 0

最后有四个过程:

1 0

为什么会这样?我真的听不懂。至少对于一个过程,结果应该是:

1 1
2 2
3 3
4 4

我希望你们中更了解MPI我的人可以帮助我。

麻烦来自index_i的论点,index_jBuild_mpi_type()。此函数将计算pair<int,int>firstsecond元素之间的偏移量。因此,index_i应指向第一个元素,index_j指向同一对的第二个元素。

像这样的东西应该可以解决问题:

 int* index_i=NULL;
 int* index_j=NULL;
 pair<int,int> bla;
 index_i=&(bla.first);
 index_j=&(bla.second);

您将需要更改函数Build_mpi_type()的原型。

 void Build_mpi_type( int* i,  int* j, MPI_Datatype* mytype)

最好ij抑制参数并创建一个专用函数Build_mpi_type_pairint(MPI_Datatype* mytype)......

您也可以添加disp[0]=0;(即使它没有它也能工作......

再见

弗朗西斯

如果你可以依赖boost库,看看Boost.MPI,我认为它支持通过boost.serialization进行序列化,也许支持对。