Problem with MPI_Gatherv for std::vector

2019-02-27 16:00发布

问题:

I'm having trouble getting MPI_Gatherv to work with a std::vector. I have written a small program that should fill a vector with integers of rank+1 (to avoid 0 as the vector is initialized to 0s). This is just an example program to run with 2 MPI processes, I realize that it is not very scalable.

#include <iostream>
#include <vector>
#include "mpi.h"


int main(int argc, char **argv)
{
    int my_rank;    //rank of process
    int p;          //number of MPI processes
    int tag=50;     //Tag for message

    int X = 32;

    MPI_Init(&argc, &argv);
    MPI_Comm_rank(MPI_COMM_WORLD, &my_rank);
    MPI_Comm_size(MPI_COMM_WORLD, &p);

    std::vector<int> rcvvec(X);
    std::vector<int> sndvec(X/p);

    int rcounts[p];
    int rdisp[p];

    for(int i=0; i<p; ++i) {
            rcounts[i] = X/p;
            rdisp[i] = my_rank*(X/p);
    }

    for (int i = 0; i < X/p; ++i)
            sndvec[i] = my_rank+1;

    MPI_Gatherv(&sndvec.front(), rcounts[my_rank], MPI_INT, &rcvvec.front(), rcounts, rdisp, MPI_INT, 0, MPI_COMM_WORLD);

    if (!my_rank) {
            for (int i = 0; i < rcvvec.size(); ++i) {
                    std::cout<<rcvvec[i]<<" ";
            } std::cout<<std::endl;
    }

    MPI_Finalize();
}

I would expect rcvvec to contain 1111111122222222

but instead I get 2222222200000000

So for some reason it only inserts process 1's integers in the first half of the vector. Does anyone have any idea what's going on here? I have also tried implementing it with a normal C style array and I get the same result. But if I write it in C instead of C++ it works. Is this a failing in my understanding of C++ and MPI?

Thanks for the help!

回答1:

The issue isn't with std::vector; there's just a typo in your code calculating the displacements. This:

for(int i=0; i<p; ++i) {
        rcounts[i] = X/p;
        rdisp[i] = my_rank*(X/p);
}

Should be this:

for(int i=0; i<p; ++i) {
        rcounts[i] = X/p;
        rdisp[i] = i*(X/p);
}

As it was, for rank zero (which in this case is the only place where the displacement array matters), all the displacements were zero, so everything was getting written to the start of the array, and the second half of the array was untouched.



标签: c++ mpi