通过MPI传递Armadillo C++矩阵
Pass an Armadillo C++ matrix over MPI
我需要通过MPI传递Armadillo C++矩阵库定义的矩阵或复杂矩阵类型。对此有什么好方法?我想尝试:
-
将矩阵写入某种数组,然后发送
其中的行/列,以及对MPI_send
/recv
两侧的阵列进行分解/重建的方法 -
使用类似
MPI_BYTE
类型的东西?
感谢
更新
因此,我试图通过在一个节点上发送和接收来实现另一种方案。
translate.cpp
#include <mpi.h>
#include <armadillo>
#include <vector>
#include <cstdlib>
using namespace std;
using namespace arma;
using std::vector;
class ArmadilloMPI
{
public:
ArmadilloMPI(int nRows, int nCols)
{
this->nRows = nRows;
this->nCols = nCols;
realArray = (double **)malloc(nCols * nRows * sizeof(double*));
imArray = (double **)malloc(nCols * nRows * sizeof(double*));
}
~ArmadilloMPI()
{
free(realArray[0]);
free(realArray);
free(imArray[0]);
free(imArray);
}
double **realArray;
double **imArray;
int nCols;
int nRows;
cx_mat matConstructRecv(int src, int tag)
{
cx_mat A(nRows, nCols);
MPI_Recv(&(imArray[0][0]), nRows * nCols, MPI_DOUBLE, src, tag, MPI_COMM_WORLD,0);
MPI_Recv(&(realArray[0][0]),nRows * nCols, MPI_DOUBLE, src, tag, MPI_COMM_WORLD,0);
for(int i = 0; i < nRows; ++i )
{
for(int j = 0; i < nCols; ++j)
{
real(A(i,j)) = *realArray[i * nRows + j];
imag(A(i,j)) = *imArray[i * nRows + j];
}
}
return A;
}
void matDestroySend(cx_mat &A, int dest, int tag)
{
for(int i = 0; i < nRows; ++i )
{
for(int j = 0; i < nCols; ++j)
{
realArray[i * nRows + j] = &real(A(i,j));
imArray[i * nRows + j] = &imag(A(i,j));
}
}
MPI_Send(&(realArray[0][0]), nRows * nCols, MPI_DOUBLE, dest, tag, MPI_COMM_WORLD);
MPI_Send(&(imArray[0][0]), nRows * nCols, MPI_DOUBLE, dest, tag, MPI_COMM_WORLD);
}
};
int main(int argc, char** argv)
{
MPI::Init(argc, argv);
int size = MPI::COMM_WORLD.Get_size();
int rank = MPI::COMM_WORLD.Get_rank();
cout << "test"<<endl;
vector<cx_mat> world;
for(int i = 0; i < size; ++i )
{
world.push_back(randu<cx_mat>(4,4));
}
cx_mat A;
A = randu<cx_mat>(4,4);
ArmadilloMPI* armaMPI = new ArmadilloMPI(4,4);
if(rank==0)
{
for(int i = 1; i < size; i++)
{
cout << "A is now " << A << endl;
A += armaMPI->matConstructRecv(i, 0);
}
}
else
{
armaMPI->matDestroySend(world[rank], 1, 0);
}
cout << A << endl;
delete armaMPI;
MPI::Finalize();
}
但我们有一个seg错误。
*** Process received signal ***
Signal: Segmentation fault: 11 (11)
Signal code: (0)
Failing at address: 0x0 translate(1032,0x7fff747ad310) malloc: *** error for object 0x41434d5f49504d4f: pointer being freed was not allocated
想法?
有几个问题:
-
在c和c++中,数组和向量从0开始,而不是从1开始。因此以下代码将失败:
vector<cx_mat> world; world.resize(1); world[1] = randu<cx_mat>(4,4); //problem to come !
您可以更改为:
vector<cx_mat> world; world.push_back(randu<cx_mat>(4,4));
-
具有连续内存的2D阵列的动态分配。对于双精度数组,需要一个
new
,对于双精度指针数组,需要另一个new
。然后将每个指针设置为指向该行的第一项。double *data=new double[nCols * nRows ]; realArray = new double*[( nRows )]; for(int i=0;i<nRows;i++){ realArray[i]=&data[i*nCols]; }
-
你可以猜到这个。。。为什么编译器不警告这类东西?因为这是有道理的,但在这里没有。
for(int j = 0; i < nCols; ++j)
-
您可以为每条消息添加不同的标签,以避免切换真实部分和想象部分
MPI_Send(&(realArray[0][0]), nRows * nCols, MPI_DOUBLE, dest, tag, MPI_COMM_WORLD); MPI_Send(&(imArray[0][0]), nRows * nCols, MPI_DOUBLE, dest, tag+1, MPI_COMM_WORLD);
代码变为:
#include <mpi.h>
#include <armadillo>
#include <vector>
#include <iostream>
#include <cstdlib>
using namespace std;
using namespace arma;
using std::vector;
class ArmadilloMPI
{
public:
ArmadilloMPI(int nRows, int nCols)
{
this->nRows = nRows;
this->nCols = nCols;
double *data=new double[nCols * nRows ];
realArray = new double*[( nRows )];
for(int i=0;i<nRows;i++){
realArray[i]=&data[i*nCols];
}
double *datai=new double[(nCols * nRows )];
imArray =new double*[( nRows )];
for(int i=0;i<nRows;i++){
imArray[i]=&datai[i*nCols];
}
}
~ArmadilloMPI()
{
delete[] realArray[0];
delete[] realArray;
delete[] imArray[0];
delete[] imArray;
}
double **realArray;
double **imArray;
int nCols;
int nRows;
cx_mat matConstructRecv(int tag, int src)
{
cx_mat A(nRows, nCols);
MPI_Recv(&(imArray[0][0]), nRows * nCols, MPI_DOUBLE, src, tag+1, MPI_COMM_WORLD,0);
MPI_Recv(&(realArray[0][0]),nRows * nCols, MPI_DOUBLE, src, tag, MPI_COMM_WORLD,0);
for(int i = 0; i < nRows; ++i )
{
for(int j = 0; j < nCols; ++j)
{
real(A(i,j)) = realArray[i][j];
imag(A(i,j)) = imArray[i][j];
}
}
return A;
}
void matDestroySend(cx_mat &A, int dest, int tag)
{
for(int i = 0; i < nRows; ++i )
{
for(int j = 0; j < nCols; ++j)
{
realArray[i][j] = real((A(i,j)));
imArray[i][j] = imag((A(i,j)));
}
}
MPI_Send(&(realArray[0][0]), nRows * nCols, MPI_DOUBLE, dest, tag, MPI_COMM_WORLD);
MPI_Send(&(imArray[0][0]), nRows * nCols, MPI_DOUBLE, dest, tag+1, MPI_COMM_WORLD);
}
};
int main(int argc, char **argv)
{
int rank;
int size;
MPI_Init(&argc, &argv);
MPI_Comm_size(MPI_COMM_WORLD, &size);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
srand (time(NULL)+rank);
vector<cx_mat> world;
world.push_back(randu<cx_mat>(4,4));
cx_mat A;
ArmadilloMPI* armaMPI = new ArmadilloMPI(4,4);
if(rank==0)
{
world[0].print("world[0] on 0:");
armaMPI->matDestroySend(world[0], 1, 0);
}
if(rank==1){
A = armaMPI->matConstructRecv(0, 0);
A.print("A on 1:");
}
delete armaMPI;
MPI_Finalize();
}
编译:
mpiCC -O2 -o main main.cpp -larmadillo -llapack -lblas -Wall
要运行:
mpiexec -np 2 main
相关文章:
- 在执行其他功能的同时播放动画(LED矩阵和Arduino/ESP8266)
- 使用std::vector的OpenCL矩阵乘法
- 使用C++中的模板和运算符重载执行矩阵运算
- Eigen如何在容器循环中干净地附加矩阵
- 当在带有Eigen的C++中使用GDB时,我如何才能看到更多的大矩阵
- 具有N列和N行的矩阵,列必须具有N-1、N-2等值
- 如何声明特征矩阵,然后通过嵌套循环初始化它
- GCC本机矩阵运算库
- 矩阵向量乘法(cublasDgemv)返回零
- 以螺旋方式打印矩阵的程序.(工作不好)
- OpenCV C++.快速计算混淆矩阵
- 特征::矩阵<双精度,1,3> 结构类型函数中的返回类型函数
- 在c++中初始化矩阵时出现分段错误(核心转储)
- 旋转模型矩阵时的形状失真
- 讨论 - 创建矩阵时的数组与向量的向量 - 什么是最实用的选择
- 如何在cuSparse中得到稀疏矩阵的对角线
- 将特征矩阵的向量设置为0
- 从C++中的数字输入动态创建矩阵
- 特征:模板函数中矩阵的平面图
- 通过常量引用传递参数的矩阵模板类