2011-09-21 48 views
3

我想送存儲在STL向量形式如何使用C++ STL向量通過Boost MPI發送矩陣的列?

vector < vector <double> > A (10, vector <double> (10)); 

矩陣的多列,而不滿足於升壓MPI複製到某些緩存(因爲計算時間是在這裏至關重要)。

我發現,MPI如何做到這一點。下面是示例代碼如何從一個進程(rank == 0)向另一個進程(rank == 1)發送10×10矩陣的第4,5,6列。 (即使我不知道爲什麼我必須在MPI_Typ_vector的第三個參數中添加'2',有人知道爲什麼?)。

int rank, size; 
    MPI_Init (&argc, &argv);  /* starts MPI */ 
    MPI_Comm_rank (MPI_COMM_WORLD, &rank); /* get current process id */ 
    MPI_Comm_size (MPI_COMM_WORLD, &size); /* get number of processes */ 

    // fill matrices 
    vector< vector <float> >A(10, vector <float> (10)); 
    vector< vector <float> >A_copy(10, vector <float> (10)); 
    for (int i=0; i!=10; i++) 
    { 
      for (int j=0; j!=10; j++) 
      { 
        A[i][j]=j+ i*10; 
        A_copy[i][j]=0.0; 
      } 
    } 

    int dest=1; 
    int tag=1; 
    // define new type = two columns 
    MPI_Datatype newtype; 
    MPI_Type_vector(10,  /* # column elements */ 
    3,      /* 3 column only */ 
    10+2,     /* skip 10 elements */ 
    MPI_FLOAT,    /* elements are float */ 
    &newtype);    /* MPI derived datatype */ 
    MPI_Type_commit(&newtype); 

    if (rank==0) 
    { 
      MPI_Send(&A[0][4], 1, newtype, dest, tag, MPI_COMM_WORLD); 
    } 
    if (rank==1) 
      MPI_Status status; 
      MPI_Recv(&A_copy[0][4], 1, newtype, 0, tag, MPI_COMM_WORLD, &status); 
    } 
    MPI_Finalize(); 

在升壓網頁,他們聲稱MPI_Type_vector是 「在Boost.MPI自動使用」(http://www.boost.org/doc/libs/1_47_0/doc/html/mpi/tutorial。 HTML#mpi.c_mapping)。

但我找不到一個例子如何做到這一點的細節。在只知道如何發送整個矩陣或每個元素與Boost後。

謝謝你在前進,

托比亞斯

回答

2

我通過編寫自己的類「列」並將其序列化來解決問題。下面是一個例子代碼:

#include<iostream> 
#include<vector> 
#include <boost/mpi/environment.hpp> 
#include <boost/mpi/communicator.hpp> 
#include <boost/serialization/vector.hpp> 
#include <boost/serialization/complex.hpp> 

using namespace std; 
namespace mpi=boost::mpi; 

class columns 
{ 
public: 
int Nr; 
int Nc; 
int J0; 
int J1; 
vector < vector <double> >* matrix; 

columns(vector < vector <double> > & A, int j0, int j1) 
{ 
    this->matrix=&A; 
    this->Nr=A.size(); 
    this->Nc=A[0].size(); 
    this->J0=j0; 
    this->J1=j1; 
} 
columns(vector < vector <double> > & A) 
{ 
    this->matrix=&A; 
    this->Nr=A.size(); 
    this->Nc=A[0].size(); 
} 
columns(){}; 
}; 

namespace boost { 
namespace serialization { 

    template<class Archive> 
    void serialize(Archive & ar, columns & g, const unsigned int version) 
    { 
     ar & g.Nr; 
     ar & g.Nc; 
     ar & g.J0; 
     ar & g.J1; 

     for (int i=0; i!=g.Nr; i++) 
     {  
      for (int j=g.J0; j!=g.J1; j++) 
      {  
       ar & (*g.matrix)[i][j]; 
      } 
     } 
    } 
} 
} 


int main(int argc, char * argv[]) 
{ 
mpi::environment env(argc, argv); 
mpi::communicator world; 
int myid=world.rank(); 
int NN=world.size(); 

int Nl=3; 
int Ng=5; 

int myStart=myid*Ng/NN; 
int myEnd=(myid+1)*Ng/NN; 
int myN=myEnd-myStart; 

if (myid==0) 
{ 
    vector < vector <double> > input (Nl, vector <double> (Ng)); 
    for (int n=0; n!=Nl; n++) 
    { 
     for (int j=0; j!=Ng; j++) 
     { 
      input[n][j]=n+j; 
     } 
    } 

    cout << "##### process " << myid << " ############" << endl; 
    for (int n=0; n!=Nl; n++) 
    { 
     for (int j=0; j!=Ng; j++) 
     { 
      cout << input[n][j] << "\t"; 
     } 
     cout << endl; 
    } 
    cout << "############################" << endl; 

    // divide grid for parallization 
    vector<int> starts(NN); 
    vector<int> ends(NN); 
    vector<int> Nwork(NN); 
    for (int p=0; p!=NN; p++) 
    { 
     starts[p]=p*Ng/NN; 
     ends[p]=(p+1)*Ng/NN; 
     Nwork[p]=ends[p]-starts[p]; 
    } 


    vector<columns> input_columns(NN); 
    for (int p=1; p!=NN; p++) 
    { 
     input_columns[p]=columns(input, starts[p], ends[p]); 
    } 


    for (int p=1; p!=NN; p++) 
    { 
     world.send(p, 1, input_columns[p]); 
    } 
} 

if (myid!=0) 
{ 
    vector < vector <double> > input (Nl, vector <double> (Ng)); 
    for (int n=0; n!=Nl; n++) 
    { 
     for (int j=0; j!=Ng; j++) 
     { 
      input[n][j]=0.0; 
     } 
    } 

    columns input_columns = columns(input, myStart, myEnd); 

    world.recv(0, 1, input_columns); 


    cout << "##### process " << myid << " ############" << endl; 
    for (int n=0; n!=Nl; n++) 
    { 
     for (int j=0; j!=Ng; j++) 
     { 
      cout << input[n][j] << "\t"; 
     } 
     cout << endl; 
    } 
    cout << "############################" << endl; 
} 
} 

說明:「columns'級包含一個指向基體和兩個數字表示其中列的開始和結束。

class columns 
{ 
    public: 
    int Nr;    // number of rows in the matrix 
    int Nc;    // number of columns in the matrix 
    int J0;    // column start index 
    int J1;    // column end index 
    vector < vector <double> >* matrix; 

    columns(vector < vector <double> > & A, int j0, int j1) 
    { 
      this->matrix=&A; 
      this->Nr=A.size(); 
      this->Nc=A[0].size(); 
      this->J0=j0; 
      this->J1=j1; 
    } 
    columns(vector < vector <double> > & A) 
    { 
      this->matrix=&A; 
      this->Nr=A.size(); 
      this->Nc=A[0].size(); 
    } 
    columns(){}; 
}; 

用下面的代碼,一本講述提振-系列化如何序列化這個「columns'級:

namespace boost { 
    namespace serialization { 

      template<class Archive> 
      void serialize(Archive & ar, columns & g, const unsigned int version) 
      { 
        ar & g.Nr; 
        ar & g.Nc; 
        ar & g.J0; 
        ar & g.J1; 

        for (int i=0; i!=g.Nr; i++) 
        { 
          for (int j=g.J0; j!=g.J1; j++) 
          { 
            ar & (*g.matrix)[i][j]; 
          } 
        } 
      } 
    } 
} 

然後一個填滿基 '輸入'

vector < vector <double> > input (Nl, vector <double>(Ng)); 
      for (int n=0; n!=Nl; n++) 
      { 
        for (int j=0; j!=Ng; j++) 
        { 
          input[n][j]=n+j; 
        } 
      } 

和初始化列類對象(現在包含指向矩陣'輸入'的指針):

vector<columns> input_columns(NN) 

和由

world.send(p, 1, input_columns); 

它發送到另一個(分)處理。在它是由

world.recv(0, 1, input_columns); 
0

如果你打算做大量列操作對,也許你應該存儲轉置,而不是A.這將使列連續存儲器位置。這意味着您可以使用MPI_Send發送列而無需執行任何複製操作。此外,列操作將更快。

+0

感謝您的回答接收到結束。但是我需要在程序的另一點處理矩陣A [i]的行。例如。將行A [i]作爲參數傳遞給期望向量的函數。因此,我不能在不復制整個矩陣的情況下切換行和列。無論如何,應該有一種方法來做到這一點與提升mpi,因爲它是適用於mpi。 – tstollenw