2015-03-01 3 views
0

Я пытаюсь обрабатывать некоторые динамически распределенные многомерные массивы в C++ с использованием MPI. Чтобы не беспокоиться о несмежной памяти, я написал оболочку класса, которая позволяет мне получить доступ к массиву 1d, как если бы это было 2d. Я пытаюсь создать тип данных MPI для отправки экземпляров класса через MPI_Send.MPI_Send + struct + динамическое распределение памяти

Мой код ниже. Когда я отправляю каждый элемент класса в свой собственный буфер MPI_Send, он дает ожидаемые результаты. Когда я пытаюсь использовать свой собственный тип данных MPI, он дает ошибку сегментации. Комментируя/раскомментируя несколько строк, вы можете попробовать оба способа.

Класс использует массивы прямо сейчас, но также получаю те же результаты с векторами. Комментируя/раскомментируя несколько строк, вы также можете попробовать это.

#include "mpi.h" 
#include <stdio.h> 
#include <vector> 
using namespace std; 

//. arrays will be this big 
const int N(2); 

//. this class is a lightweight wrapper around a 1d vector so that it can be accessed as 2d. this 
//. ensures that the memory use is contiguous, so it can be sent through mpi. by commenting/ 
//. uncommenting, it can be set to use either a vector or an array. 
template <class type> class arr2d{ 
    public: 
    int s[2]; //. size (length and width) 
/* vector<type> v; */ //. vector data container 
    type* v; //. array data container 
/* void init(const int& s0, const int& s1){s[0] = s0; s[1] = s1; v.resize(s[0]*s[1]);} */ 
    void init(const int& s0, const int& s1){s[0] = s0; s[1] = s1; v = new type[s[0]*s[1]];} 
    type& operator()(const int& i, const int& k){return v[s[1]*i + k];} 
}; 

int main(){ 
    //. standard mpi stuff 
    int mpi_rank, mpi_size; 
    MPI_Status stat; 

    //. declare an arr2d object 
    arr2d<double> x; 
    x.init(N,N); 

    //. displacements, types, and elements (for mpi_type_create_struct) 
    MPI_Aint  disp[2]; 
    MPI_Datatype type[2]; 
    int   elts[2]; 

    //. this will hold the arr2d mpi data type 
    MPI_Datatype mpi_arr2d; 

    //. fire up mpi 
    MPI_Init(NULL,NULL); 
    MPI_Comm_rank(MPI_COMM_WORLD,&mpi_rank); 
    MPI_Comm_size(MPI_COMM_WORLD,&mpi_size); 

    //. put some values in the rank 0 version of x 
    if(mpi_rank == 0){ 
    for(int i=0;i<N;i++){ 
     for(int k=0;k<N;k++){ 
     x(i,k) = i+k+0.5; 
     } 
    } 
    } else { //. rank 1 starts with x full of zeros 
    for(int i=0;i<N;i++){ 
     for(int k=0;k<N;k++){ 
     x(i,k) = 0; 
     } 
    } 
    } 

    //. displaceemnt of elements of x (vector implementation) 
/* disp[0] = (int*)&x.s - (int*)&x; 
    disp[1] = (int*)&x.v.front() - (int*)&x; */ 

    //. displaceemnt of elements of x (array implementation) 
    disp[0] = (int*)&x.s - (int*)&x; 
    disp[1] = (int*)&x.v[0] - (int*)&x; 

    //. types of elements of x 
    type[0] = MPI_INT; 
    type[1] = MPI_DOUBLE; 

    //. quantities of elements of x 
    elts[0] = 2; 
    elts[1] = N*N; 

    //. assemble and commit mpi_arr2d 
    MPI_Type_create_struct(2,elts,disp,type,&mpi_arr2d); 
    MPI_Type_commit(&mpi_arr2d); 

    //. check what each rank sees before communication 
    printf("rank %d sees %f %f %f %f \n",mpi_rank,x(0,0),x(0,1),x(1,0),x(1,1)); 

    if(mpi_rank == 0){ 
    MPI_Send(&x,1,mpi_arr2d,1,123,MPI_COMM_WORLD); 
/* MPI_Send(&x.s,2,MPI_INT,1,124,MPI_COMM_WORLD); */ //. send just the size 
/* MPI_Send(&x.v.front(),N*N,MPI_DOUBLE,1,125,MPI_COMM_WORLD); */ //. send just the vector 
/* MPI_Send(&x.v[0],N*N,MPI_DOUBLE,1,125,MPI_COMM_WORLD); */ //. send just the array 
    printf("just send to rank 1\n"); 
    } 
    if(mpi_rank == 1){ 
    MPI_Recv(&x,1,mpi_arr2d,0,123,MPI_COMM_WORLD,&stat); 
/* MPI_Recv(&x.s,2,MPI_INT,0,124,MPI_COMM_WORLD,&stat); */ //. recv the size 
/* MPI_Recv(&x.v.front(),N*N,MPI_DOUBLE,0,125,MPI_COMM_WORLD,&stat); */ //. recv the vector 
/* MPI_Recv(&x.v[0],N*N,MPI_DOUBLE,0,125,MPI_COMM_WORLD,&stat); */ //. recv the array 
    printf("just recved from rank 0\n"); 
    } 

    //. check what each rank sees after communication 
    printf("rank %d sees %f %f %f %f \n",mpi_rank,x(0,0),x(0,1),x(1,0),x(1,1)); 

    MPI_Finalize(); 
    return 0; 
} 
+1

'Комментируя/раскомментируя несколько строк, вы можете попробовать в обоих направлениях. Так что вы опубликовали версию, без каких-либо дальнейших манипуляций, ту, которая работает, или тот, который не работает? – PaulMcKenzie

+0

Версия выше не работает. Изменение int * на char * заставляет все работать (за Dr. Tower). – Charles

ответ

1

Я думаю, что проблема в том, что у вас есть (int*) указатель проливает при расчете смещения, когда значения смещения должны быть в байтах. Я смог заставить его работать, используя (char*) приведение указателей при вычислении значений disp[0] и disp[1].

(void*) не собирался для меня.

+0

Это работало как для массива, так и для векторных реализаций. Благодаря! – Charles

+0

Не могли бы вы принять ответ тогда :) –

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