Я решил проблему, написав свой собственный класс 'столбцы' и сериализовав его. Вот пример кода:
#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(){};
};
С помощью следующего кода мы сообщаем boost-serialization, как сериализовать этот класс '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;
}
}
и инициализировать объект класса columns (который теперь содержит указатель на матрицу 'input'):
vector<columns> input_columns(NN)
и отправить его другому (под) процессу по
world.send(p, 1, input_columns);
В конце концов его получает
world.recv(0, 1, input_columns);