MPI_Gather мусор в приемном буфере (MPI + C) - PullRequest
0 голосов
/ 23 мая 2018

Я новичок в MPI и пытаюсь распараллелить код на нескольких потоках.Мне нужно передать большой кусок данных обратно в главный поток, и я не могу очистить мусор памяти, который я получаю после MPI_Gather.Вот пример кода:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <mpi.h>

int main (int argc, char *argv[]) {

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

double *total=NULL;
double parcial[15000];
int W=world_size*15000;

if (rank == 0) {
    total=malloc(sizeof(double) * world_size*15000);
}
else if (rank != 0) {
    for(int i=0; i<15000; i++)parcial[i] = rank*i*0.1;
}
MPI_Barrier(MPI_COMM_WORLD);

if(rank==0) for(int ii=0; ii<W; ii++)total[ii]=0.;

MPI_Gather(parcial,15000,MPI_DOUBLE,total,15000,MPI_DOUBLE,0,MPI_COMM_WORLD);

if (rank == 0) {
    int N=world_size*15000;
    for(int i=0; i<N; i++) printf("%f ", total[i]);
}

free(total);
MPI_Finalize();

}

Если вы запускаете код с несколькими потоками (я пробовал 3,4,5 ...), он всегда имеет мусор в начале буфера приема, хотяЯ явно установил total [ii] в ноль перед вызовом MPI_Gather и установил барьер.Это потому, что у меня физически только два ядра?Но я читал, что MPI все равно создает виртуальную машину.Есть ли способ очистить его и получить надежный сбор?

Дополнение:

Я полагал, что этот мусор, вероятно, приходит из нулевого потока.Почему он не обнуляется после строки 25?

1 Ответ

0 голосов
/ 24 мая 2018

Выдержка из справочной страницы MPI для MPI_Gather:

Каждый процесс (включая корневой процесс) отправляет содержимое своего буфера отправки в корневой процесс.

Таким образомпервые 15000 элементов буфера recv total будут содержать элементы parcial в корневом процессе.Это было оставлено в вашем коде унифицированным.

Редактировать: @Gilles прокомментировал, что MPI_IN_PLACE можно использовать, чтобы избежать инициализации корневого процесса.Вот пример, показывающий его эффект:

#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <mpi.h>


int main(int argc, char *argv[])
{
    int rank, size;

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

    int *in_place_total = calloc(sizeof(int), size);
    int *total = calloc(sizeof(int), size);

    int sendval = rank-5000;

    MPI_Gather(&sendval, 1, MPI_INT,
           total, 1, MPI_INT, 0, MPI_COMM_WORLD);

    if (rank == 0)
        assert(total[0] == -5000);

    if (rank)
        MPI_Gather(&sendval, 1, MPI_INT,
           in_place_total, 1, MPI_INT, 0, MPI_COMM_WORLD);
    else
        MPI_Gather(MPI_IN_PLACE, 1, MPI_INT,
           in_place_total, 1, MPI_INT, 0, MPI_COMM_WORLD);

    if (rank == 0)
        assert(in_place_total[0] == 0);

    free(total);
    free(in_place_total);

    MPI_Finalize();

}
...