Проблема с MPI_Gatherv для std::vector

У меня не получается заставить MPI_Gatherv работать с std::vector. Я написал небольшую программу, которая должна заполнять вектор целыми числами ранга + 1 (чтобы избежать 0, поскольку вектор инициализируется 0). Это всего лишь пример программы для запуска с двумя процессами MPI, я понимаю, что она не очень масштабируема.

#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();
}

Я ожидаю, что rcvvec будет содержать 1111111122222222

но вместо этого я получаю 2222222200000000

Поэтому по какой-то причине он вставляет целые числа процесса 1 только в первую половину вектора. Кто-нибудь знает, что здесь происходит? Я также пытался реализовать его с обычным массивом стиля C, и я получаю тот же результат. Но если я напишу это на C вместо C++, это сработает. Является ли это недостатком моего понимания C++ и MPI?

Спасибо за помощь!


person Tim B    schedule 18.02.2011    source источник


Ответы (1)


Проблема не в std::vector; у вас просто опечатка в коде, вычисляющем смещения. Этот:

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

Должно быть так:

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

Как бы то ни было, для нулевого ранга (в данном случае это единственное место, где имеет значение массив смещений) все смещения были равны нулю, поэтому все записывалось в начало массива, а вторая половина массива оставалась нетронутой. .

person Jonathan Dursi    schedule 18.02.2011