Я убедился, что MPI_Gather
собирает данные со всех процессов, включая сам корневой процесс.
Как заставить MPI_Gather
собирать данные со всех процессов, НЕ включая сам корневой процесс? Или есть альтернативная функция?
Я убедился, что MPI_Gather
собирает данные со всех процессов, включая сам корневой процесс.
Как заставить MPI_Gather
собирать данные со всех процессов, НЕ включая сам корневой процесс? Или есть альтернативная функция?
Дублируйте функциональность 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);