mpi собирать данные

Я убедился, что MPI_Gather собирает данные со всех процессов, включая сам корневой процесс.

Как заставить MPI_Gather собирать данные со всех процессов, НЕ включая сам корневой процесс? Или есть альтернативная функция?


person Nurlan    schedule 29.11.2012    source источник


Ответы (1)


Дублируйте функциональность MPI_Gather, используя MPI_Gatherv, но вместо этого укажите 0 в качестве размера фрагмента для корневого ранга. Что-то вроде этого:

int rank, size, disp = 0;
int *cnts, *displs;

MPI_Comm_size(MPI_COMM_WORLD, &size);

cnts = malloc(size * sizeof(int));
displs = malloc(size * sizeof(int));
for (rank = 0; rank < size; rank++)
{
    cnts[i] = (rank != root) ? count : 0;
    displs[i] = disp;
    disp += cnts[i];
}

MPI_Comm_rank(MPI_COMM_WORLD, &rank);

MPI_Gatherv(data, cnts[rank], data_type,
            bigdata, cnts, displs, data_type,
            root, MPI_COMM_WORLD);

free(displs); free(cnts);

Обратите внимание, что MPI_Gatherv может быть значительно медленнее, чем MPI_Gather, потому что реализация MPI, скорее всего, не сможет оптимизировать коммуникационный путь и вернется к какой-то тупой линейной реализации операции сбора. Поэтому может иметь смысл по-прежнему использовать MPI_Gather и предоставлять некоторые фиктивные данные в корневом процессе.

Вы также можете указать MPI_IN_PLACE в качестве значения буфера отправки корневого процесса, и он не будет отправлять данные самому себе, но опять же вам придется зарезервировать место для корневых данных в буфере приема (операция на месте ожидает, что корень поместит свои данные непосредственно в правильную позицию внутри буфера приема):

if (rank != root)
    MPI_Gather(data, count, data_type,
               NULL, count, data_type, root, MPI_COMM_WORLD);
else
    MPI_Gather(MPI_IN_PLACE, count, data_type,
               big_data, count, data_type, root, MPI_COMM_WORLD);
person Hristo Iliev    schedule 29.11.2012