如何通过Boost MPI使用c++ STL矢量发送矩阵的列
How to send columns of a matrix via Boost MPI using C++ STL vectors?
我想发送一个矩阵的多列存储为STL矢量形式
vector < vector < double > > A ( 10, vector <double> (10));
而不将内容复制到某个缓冲区(因为这里的计算时间至关重要)。
我发现了如何用MPI来做到这一点。以下是示例代码如何将10 × 10矩阵的第4、第5和第6列从一个进程(秩==0)发送到另一个进程(秩==1)。(即使我不知道为什么我必须在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();
在Boost网页上,他们声称MPI_Type_vector"在Boost中自动使用"。MPI"(http://www.boost.org/doc/libs/1_47_0/doc/html/mpi/tutorial.html mpi.c_mapping)。
但是我找不到一个详细的例子。只知道如何用Boost发送整个矩阵或每个元素。
提前谢谢你
Tobias
我通过编写自己的类'columns'并序列化它来解决这个问题。下面是一个示例代码:
#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];
}
}
}
}
}
然后填充矩阵'input'
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;
}
}
和初始化一个列类对象(现在包含一个指向矩阵'input'的指针):
vector<columns> input_columns(NN)
并通过
发送给另一个(子)进程world.send(p, 1, input_columns);
最后被
接收world.recv(0, 1, input_columns);
如果你要在A上做很多列操作,也许你应该存储A的转置而不是A。这将把列放在连续的内存位置。这意味着您可以使用MPI_Send发送列,而无需执行任何复制操作。此外,列操作将更快。
相关文章:
- 将所选值(通过视图)从 boost::multi_array 复制到另一个数组 (C++)
- 如何在 Linux for Windows 上通过 MinGW 构建静态 ICU 的 Boost
- 如何通过Boost.MPI发送2d Boost.MultiArray的子阵列?
- 通过boost asio iostream下载大文件的最快方法是什么?
- 如何通过 boost::p ython 重命名构造函数的关键字参数
- 通过 Boost 和 C++ 进行 SMTP 身份验证
- C++ boost::asio https 通过代理
- 如何通过boost::asio和shared_ptr创建串行端口
- 通过 Boost Python 将 Python 函数转换为 C++,用作回调
- 通过 Boost Python 在C++对象之间传递共享指针的隔离错误
- 通过引用将自定义结构的向量传递给 boost::compute 闭包或函数
- 如何通过std ::变体正确替换boost ::变体
- 如何使用 boost asio 通过 UDP 套接字发送无符号字符的 std::vector?
- Boost Intervocess:通过迭代通过从结构引用对象的映射进行迭代时
- Boost.MSM:通过连接伪状态退出正交区域
- Boost::序列化和Boost::mpi通过基类指针广播派生类
- 使用Asio(Boost)通过网络发送灵活的数据量
- 为什么Boost.Cconcept通过空指针调用析构函数
- boost::如何通过引用/指针传递到python overriden类函数
- c++ Boost循环通过未知的ptree和列表属性值