Просто общий вопрос:
Я хотел спросить, есть ли возможность передавать элементы только определенным рангам в MPI без использования подпрограмм MPI_Send
и MPI_Recv
.
Просто общий вопрос:
Я хотел спросить, есть ли возможность передавать элементы только определенным рангам в MPI без использования подпрограмм MPI_Send
и MPI_Recv
.
Я хотел спросить, есть ли возможность передавать элементы только определенным рангам в MPI без использования MPI_Send MPI_Recv.
Начнем с описания MPI_Bcast процедура.
Рассылает сообщение от процесса с корневым рангом всем остальным процессам коммуникатора
Подпрограмма широковещательной рассылки MPI_Bcast
представляет собой коллективную коммуникацию. Следовательно:
Коллективная коммуникация — это метод коммуникации, предполагающий участие всех процессов в коммуникаторе.
Обратите внимание на текст, выделенный полужирным шрифтом, т. е. все процессы в коммуникаторе. Следовательно, один из подходов (для достижения желаемого) заключается в создании подмножества, состоящего из процессов, которые будут участвовать в подпрограмме широковещания. Это подмножество может быть реализовано путем создания нового коммуникатора< /а>. Для создания этого коммуникатора можно использовать функцию MPI MPI_Comm_split. Об этой процедуре из источника можно прочитать:
Как следует из названия,
MPI_Comm_split
создает новые коммуникаторы, "разделяя" коммуникатор на группу подчиненных коммуникаторов на основе входных значений цвета и ключа. Здесь важно отметить, что исходный коммуникатор не уходят, но для каждого процесса создается новый коммуникатор.
Первый аргумент, comm, это коммуникатор, который будет использоваться в качестве основы для новых коммуникаторов. Это может быть MPI_COMM_WORLD, но может быть и любой другой коммуникатор.
Второй аргумент, цвет, определяет, какому новому коммуникатору будет принадлежать каждый процесс. Все процессы, передающие одно и то же значение цвета, назначаются одному и тому же коммуникатору. Если цвет MPI_UNDEFINED, этот процесс не будет включен ни в один из новых коммуникаторов. Третий аргумент, ключ, определяет порядок (ранг) в каждом новом коммуникаторе. Процесс, который передает наименьшее значение для ключа, будет иметь ранг 0, следующий наименьший будет иметь ранг 1 и так далее. Если есть ничья, процесс, который имел более низкий ранг в исходном коммуникаторе, будет первым. Последний аргумент, newcomm, — это то, как MPI возвращает пользователю новый коммуникатор.
Допустим, мы хотели, чтобы в MPI_Bcast
участвовали только процессы с четным рангом; Сначала мы создадим коммуникатор:
MPI_Comm new_comm;
int color = (world_rank % 2 == 0) ? 1 : MPI_UNDEFINED;
MPI_Comm_split(MPI_COMM_WORLD, color, world_rank, &new_comm);
и, в конце концов, вызовите MPI_Bcast
для нового коммуникатора:
if(world_rank % 2 == 0){
....
MPI_Bcast(&bcast_value, 1, MPI_INT, 0, new_comm);
...
}
В конце мы бы освободили память используемую коммуникатором:
MPI_Comm_free(&new_comm);
Пример работающего кода:
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <mpi.h>
int main(int argc,char *argv[]){
MPI_Init(NULL,NULL); // Initialize the MPI environment
int world_rank;
int world_size;
MPI_Comm_rank(MPI_COMM_WORLD,&world_rank);
MPI_Comm_size(MPI_COMM_WORLD,&world_size);
int bcast_value = world_rank;
MPI_Bcast(&bcast_value, 1, MPI_INT, 0, MPI_COMM_WORLD);
printf("MPI_Bcast 1 : MPI_COMM_WORLD ProcessID = %d, bcast_value = %d \n", world_rank, bcast_value);
MPI_Comm new_comm;
int color = (world_rank % 2 == 0) ? 1 : MPI_UNDEFINED;
MPI_Comm_split(MPI_COMM_WORLD, color, world_rank, &new_comm);
if(world_rank % 2 == 0){
int new_comm_rank, new_comm_size;
MPI_Comm_rank(new_comm, &new_comm_rank);
MPI_Comm_size(new_comm, &new_comm_size);
bcast_value = 1000;
MPI_Bcast(&bcast_value, 1, MPI_INT, 0, new_comm);
printf("MPI_Bcast 2 : MPI_COMM_WORLD ProcessID = %d, new_comm = %d, bcast_value = %d \n", world_rank, new_comm_rank, bcast_value);
MPI_Comm_free(&new_comm);
}
MPI_Finalize();
return 0;
}
В этом примере кода показаны два вызова MPI_Bcast
, один со всеми процессами MPI_COMM_WORLD
(т. е. MPI_Bcast 1
), а другой — только с подмножеством этих процессов (т. е. MPI_Bcast 2
). .
Вывод (для 8 процессов):
MPI_Bcast 1 : MPI_COMM_WORLD ProcessID = 0, bcast_value = 0
MPI_Bcast 1 : MPI_COMM_WORLD ProcessID = 4, bcast_value = 0
MPI_Bcast 1 : MPI_COMM_WORLD ProcessID = 5, bcast_value = 0
MPI_Bcast 1 : MPI_COMM_WORLD ProcessID = 6, bcast_value = 0
MPI_Bcast 1 : MPI_COMM_WORLD ProcessID = 7, bcast_value = 0
MPI_Bcast 1 : MPI_COMM_WORLD ProcessID = 1, bcast_value = 0
MPI_Bcast 1 : MPI_COMM_WORLD ProcessID = 2, bcast_value = 0
MPI_Bcast 1 : MPI_COMM_WORLD ProcessID = 3, bcast_value = 0
MPI_Bcast 2 : MPI_COMM_WORLD ProcessID = 0, new_comm = 0, bcast_value = 1000
MPI_Bcast 2 : MPI_COMM_WORLD ProcessID = 4, new_comm = 2, bcast_value = 1000
MPI_Bcast 2 : MPI_COMM_WORLD ProcessID = 2, new_comm = 1, bcast_value = 1000
MPI_Bcast 2 : MPI_COMM_WORLD ProcessID = 6, new_comm = 3, bcast_value = 1000
MPI_Bcast()
. Или вы можете использоватьMPI_Scatterv()
(хотя другие элементы все равно должны вызыватьMPI_Scatterv(..., recvcount=0, ...)
. - person Gilles Gouaillardet   schedule 20.01.2021