2014-02-12 5 views
1

Я новичок в MPI, поэтому я прошу вас помочь. Мне нужно разбросать вектор пар в C++ с MPI. Для этого я создал MPI_Datatype «mytype». Затем я использую MPI_Scatterv, потому что я не хочу, чтобы разброс зависел или от размера вектора ни по количеству процессов.Scatter a C++ вектор пар с MPI

Вот мой код:

#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 может помочь мне.

ответ

0

Если вы можете положиться на библиотеки boost, взгляните на Boost.MPI, я думаю, что он поддерживал сериализацию через boost.serialization и, возможно, пары поддерживались.

1

Проблема связана с аргументами index_i и index_j от Build_mpi_type(). Эта функция будет вычислять смещение между first и second элементом pair<int,int>. Поэтому 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) 

Это может быть лучше, чтобы подавить аргументы i и j и создать специальную функцию Build_mpi_type_pairint(MPI_Datatype* mytype) ...

Вы также можете добавить disp[0]=0; (даже если он работает без него ...).

Bye,

Фрэнсис

Смежные вопросы