C++ 特征压缩稀疏矩阵的MPI接收和发送

C++ 特征压缩稀疏矩阵的MPI接收和发送,c++,mpi,sparse-matrix,eigen,eigen3,C++,Mpi,Sparse Matrix,Eigen,Eigen3,发送和接收使用特征库定义的稀疏矩阵的最佳(最快)方式是什么 目前,我仅使用非零元素创建一个值、行和列向量(来自预定义的稀疏矩阵),并逐个发送/接收这3个向量。这些向量是简单的std::vector if (0 == myrank) { Sz.insert(0,0) = 0.5; Sz.insert(1,1) = -0.5; //------ preparing to send ---------- shape[0] = Sz.rows(); shap

发送和接收使用特征库定义的稀疏矩阵的最佳(最快)方式是什么

目前,我仅使用非零元素创建一个值、行和列向量(来自预定义的稀疏矩阵),并逐个发送/接收这3个向量。这些向量是简单的std::vector

if (0 == myrank) {
    Sz.insert(0,0) = 0.5;       Sz.insert(1,1) = -0.5;

    //------ preparing to send ----------
    shape[0] = Sz.rows();
    shape[1] = Sz.cols();
    int size=Sz.nonZeros();
    val.resize(size); inner.resize(size); outer.resize(size);
    cout << "val-size = "<< val.size() << endl;
    int counter=0;
    for (int k=0; k<Sz.outerSize(); ++k) {
        for (CrsMatrixType::InnerIterator it(Sz,k); it; ++it)  {
            val[counter]=it.value();
            inner[counter]=it.col();
            outer[counter]=it.row();
            counter++;
        }
    }
    assert(counter==size);
    MPI_Send(&shape[0],2,MPI_INT,1, 100, MPI_COMM_WORLD);
    MPI_Send(&size,1,MPI_INT,1, 101, MPI_COMM_WORLD);
    MPI_Send(&val[0],size,MPI_DOUBLE,1, 102, MPI_COMM_WORLD);
    MPI_Send(&inner[0],size,MPI_INT,1, 103, MPI_COMM_WORLD);
    MPI_Send(&outer[0],size,MPI_INT,1, 104, MPI_COMM_WORLD);


}
if(0==myrank){
深插入(0,0)=0.5;深插入(1,1)=-0.5;
//------准备发送----------
shape[0]=Sz.rows();
shape[1]=Sz.cols();
int size=Sz.nonZeros();
val.resize(大小);内部.resize(大小);外部.resize(大小);

cout我通常建议使用压缩形式来传输稀疏矩阵。并且不需要将值复制到临时
std::vector
s中

void sendSparseEigen(const Ref<const SparseMatrix<double>,StandardCompressedFormat>& mat) {
    int rows=mat.rows, cols=mat.cols, nnz=mat.nonZeros();
    assert(rows==mat.innerSize() && cols==mat.outerSize());
    assert(mat.outerIndexPtr()[cols]==nnz);
    int shape[3] = {rows, cols, nnz};
    MPI_Send(shape              ,3   ,MPI_INT,   1, 100, MPI_COMM_WORLD);
    MPI_Send(mat.valuePtr()     ,nnz ,MPI_DOUBLE,1, 101, MPI_COMM_WORLD);
    MPI_Send(mat.innerIndexPtr(),nnz ,MPI_INT,   1, 102, MPI_COMM_WORLD);
    MPI_Send(mat.outerIndexPtr(),cols,MPI_INT,   1, 103, MPI_COMM_WORLD);
}

void receiveSparseEigen(SparseMatrix<double> &out){
    int shape[3];
    MPI_Recv(shape,3,MPI_INT,0, 100, MPI_COMM_WORLD, &status);
    int rows=shape[0], cols=shape[1], nnz=shape[2];
    out.resize(rows, cols);
    out.reserve(nnz);
    MPI_Recv(out.valuePtr(),  nnz, MPI_DOUBLE,0, 101, MPI_COMM_WORLD, &status);
    MPI_Recv(out.innerIndexPtr(),nnz, MPI_INT,0, 102, MPI_COMM_WORLD, &status);
    MPI_Recv(out.outerIndexPtr(),cols,MPI_INT,0, 103, MPI_COMM_WORLD, &status);
    out.outerIndexPtr()[cols] = nnz;
}
void sendSparseEigen(常数参考和材料){
int rows=mat.rows,cols=mat.cols,nnz=mat.nonZeros();
断言(rows==mat.innerSize()和&cols==mat.outerSize());
断言(mat.outerIndexPtr()[cols]==nnz);
int-shape[3]={rows,cols,nnz};
MPI_发送(形状,3,MPI_INT,1100,MPI_通信世界);
MPI_Send(mat.valuePtr(),nnz,MPI_DOUBLE,1101,MPI_COMM_WORLD);
MPI_Send(mat.innerIndexPtr(),nnz,MPI_INT,1102,MPI_COMM_WORLD);
MPI_Send(mat.outerIndexPtr(),cols,MPI_INT,1103,MPI_COMM_WORLD);
}
无效接收SPARSEEIGEN(SPARSAMTRIX&out){
int-shape[3];
MPI_Recv(形状、3、MPI_INT、0、100、MPI_COMM_WORLD和状态);
int rows=shape[0],cols=shape[1],nnz=shape[2];
out.调整大小(行、列);
输出储备(nnz);
MPI_Recv(out.valuePtr()、nnz、MPI_DOUBLE、0、101、MPI_COMM_WORLD和status);
MPI_Recv(out.innerIndexPtr()、nnz、MPI_INT、0、102、MPI_COMM_WORLD和status);
MPI_Recv(out.outerIndexPtr()、cols、MPI_INT、0、103、MPI_COMM_WORLD和status);
out.outerIndexPtr()[cols]=nnz;
}

免责声明:我不是MPI专家,我从您的示例中复制了所有与MPI相关的代码——显然您应该以某种方式处理MPI生成的所有可能错误。上面的代码未经测试。

首先,您应该一次性发送
shape
size
。然后您可以创建一个包含两个
MPI\u INT
结构e
MPI_uuuuDouble
描述矩阵的一个元素,分配并填充它,为它构建一个派生的数据类型,一次发送
size
元素。谢谢!:D我使用了下面的@chtz注释。它避免了创建临时变量,并直接将矩阵填充到秩1中。虽然我没有测试速度/内存,但效果很好显式。很明显,您的解决方案避免了创建节省内存和冗余操作的临时文件。谢谢!还有一件事,将来如果其他人正在使用此解决方案,请确保在传递.mat.makeCompressed()之前压缩稀疏矩阵;是的,您实际上可以从
Ref
中删除
StandardCompressedFormat
标志,只需
assert(mat.isCompressed());
或在第一个函数中传递非常量
SparseMatrix&
并调用
makeCompressed()
void sendSparseEigen(const Ref<const SparseMatrix<double>,StandardCompressedFormat>& mat) {
    int rows=mat.rows, cols=mat.cols, nnz=mat.nonZeros();
    assert(rows==mat.innerSize() && cols==mat.outerSize());
    assert(mat.outerIndexPtr()[cols]==nnz);
    int shape[3] = {rows, cols, nnz};
    MPI_Send(shape              ,3   ,MPI_INT,   1, 100, MPI_COMM_WORLD);
    MPI_Send(mat.valuePtr()     ,nnz ,MPI_DOUBLE,1, 101, MPI_COMM_WORLD);
    MPI_Send(mat.innerIndexPtr(),nnz ,MPI_INT,   1, 102, MPI_COMM_WORLD);
    MPI_Send(mat.outerIndexPtr(),cols,MPI_INT,   1, 103, MPI_COMM_WORLD);
}

void receiveSparseEigen(SparseMatrix<double> &out){
    int shape[3];
    MPI_Recv(shape,3,MPI_INT,0, 100, MPI_COMM_WORLD, &status);
    int rows=shape[0], cols=shape[1], nnz=shape[2];
    out.resize(rows, cols);
    out.reserve(nnz);
    MPI_Recv(out.valuePtr(),  nnz, MPI_DOUBLE,0, 101, MPI_COMM_WORLD, &status);
    MPI_Recv(out.innerIndexPtr(),nnz, MPI_INT,0, 102, MPI_COMM_WORLD, &status);
    MPI_Recv(out.outerIndexPtr(),cols,MPI_INT,0, 103, MPI_COMM_WORLD, &status);
    out.outerIndexPtr()[cols] = nnz;
}