具有子矩阵的MPI Gatherv

时间:2018-11-30 16:01:20

标签: c++ mpi eigen

我在使MPI_Gatherv达到我的预期目标时遇到了麻烦,并且想知道那些经验丰富的人可以看到我在做错什么。

我有一个[N,M]的大矩阵(TEST)。每个过程都在一个子集[rows,M](WORK_MATRIX)上做一些工作,然后每个过程(沿着行维)将这些子矩阵收集到完整的矩阵中。

似乎它没有收集任何数据,我正在努力找出原因!

在这里,我正在使用Eigen包装这些(连续的)矩阵。

输出:

mpirun -np 5 ./pseudo.x
1 1 1 1 1
0 1 2 3 4
TEST: 5 10
0 0 2 0 0 0 0 0 0 0 
1 1 2 0 0 0 0 0 0 0 
2 2 2 0 0 0 0 0 0 0 
3 2 2 0 0 0 0 0 0 0 
4 2 0 0 0 0 0 0 0 0

我创建了以下代码的简单版本:

mpiicc -I / path / to / Eigen -o pseudo.x pseudo.cpp

#include <mpi.h>
#include <Eigen/Dense>
#include <iostream>

using namespace Eigen;
using namespace std;

int main(int argc, char ** argv) {
int RSIZE = 5;
int CSIZE = 10;

int rank;
int num_tasks;

MPI_Init(&argc, &argv);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
MPI_Comm_size(MPI_COMM_WORLD, &num_tasks);

MatrixXd TEST_MATRIX = MatrixXd::Zero(RSIZE, CSIZE);

VectorXi recv = VectorXi::Zero(num_tasks);
VectorXi displs = VectorXi::Zero(num_tasks);

int nrows = (RSIZE + rank) / num_tasks;

MPI_Allgather(&nrows, 1, MPI_INT, recv.data(), 1, MPI_INT, MPI_COMM_WORLD);

int start = 0;
for (int i = 0; i < rank; i++)
    start += recv[i];

MPI_Allgather(&start, 1, MPI_INT, displs.data(), 1, MPI_INT, MPI_COMM_WORLD);

if (rank == 0) {
    cout << recv.transpose() << endl;
    cout << displs.transpose() << endl;
}

MatrixXd WORK_MATRIX = MatrixXd::Zero(nrows, CSIZE);

for (int row = 0; row < nrows; row++)
    for (int col = 0; col < CSIZE; col++)
        WORK_MATRIX(row, col) += rank;

MPI_Datatype rowsized, row;

int sizes[2] = { RSIZE, CSIZE };
int subsizes[2] = { nrows, CSIZE };
int starts[2] = { 0, 0 };
MPI_Type_create_subarray(2, sizes, subsizes, starts, MPI_ORDER_C, MPI_DOUBLE, &rowsized);
MPI_Type_create_resized(rowsized, 0, sizeof(double), &row);
MPI_Type_commit(&row);

MPI_Allgatherv(WORK_MATRIX.data(), recv[rank], row, TEST_MATRIX.data(), recv.data(), displs.data(), row, MPI_COMM_WORLD);

if (rank == 0) {
    cout << "TEST: " << TEST_MATRIX.rows() << " " << TEST_MATRIX.cols() << endl;

    for (int i = 0; i < TEST_MATRIX.rows(); i++) {
        for (int j = 0; j < TEST_MATRIX.cols(); j++) {
            cout << TEST_MATRIX(i, j) << " ";
        }
        cout << endl;
    }
}

}

1 个答案:

答案 0 :(得分:0)

C中,二维矩阵按行存储,我怀疑本征会改变这种情况。

这意味着您无需调整数据类型的大小,并且应该调整位移

start += recv[i] * CSIZE;

从品味上讲,您根本不需要两个MPI_Allgather(),因为nrowsstart可以在本地计算。 我宁愿建议您仅使用MPI_Type_contiguous()为一行创建一个派生数据类型(并且该类型不应调整大小),因为MPI_Type_create_subarray()在这里实在是太过分了。