| | | |

Computação Paralela com C++

Ajude a manter o site livre, gratuito e sem propagandas. Colabore!

3.5 Grupos e comunicadores

Em construção

Comunicadores são objetos que definem grupos de processos que podem se comunicar entre si. Cada comunicador é associado a um grupo de processos, e as operações de comunicação são realizadas dentro desse grupo.

3.5.1 MPI_Comm_Split

Uma das funções mais comumente empregadas para criar um novo comunicador é a MPI_Comm_split. Sua sintaxe é a seguinte:

1int MPI_Comm_split(
2 MPI_Comm comm,
3 int color,
4 int key,
5 MPI_Comm *newcomm)

O argumento comm é o comunicador original (por exemplo, MPI_COMM_WORLD), color é um inteiro que define a cor do grupo de processos que serão incluídos no novo comunicador. Todos os processos que passam pelo mesmo valor de color são atribuídos aos mesmo comunicador. Se color == MPI_UNDEFINED, o processo não é atribuído a nenhum novo comunicador. E, key é um inteiro que define a ordem dos processos no novo comunicador. O processo que passa com o menor valor de key será o rank == 0 no novo comunicador, o próximo com menor valor será o rank == 1 e assim por diante. O argumento newcomm é um ponteiro para o novo comunicador criado.

Exemplo 3.5.1.

O seguinte Código 15 cria dois grupos de processos, um com color == 0 e outro com color == 1. Os processos são distribuídos dois-a-dois entre os comunicadores. Consulte a Figura 3.7.

Refer to caption
Figura 3.7: Criação de novos comunicadores com MPI_Comm_split.
Código 15: comm_split.cpp
1// Initialize MPI
2MPI_Init(nullptr, nullptr);
3
4int world_size;
5MPI_Comm_size(MPI_COMM_WORLD, &world_size);
6int world_rank;
7MPI_Comm_rank(MPI_COMM_WORLD, &world_rank);
8
9// create a new communicator
10int color = world_rank / 2;
11
12MPI_Comm new_comm;
13MPI_Comm_split(MPI_COMM_WORLD, color, world_rank, &new_comm);
14
15int new_rank, new_size;
16MPI_Comm_rank(new_comm, &new_rank);
17MPI_Comm_size(new_comm, &new_size);
18
19printf("World Rank/Size: %d/%d, New Rank/Size: %d/%d, Color: %d\n",
20 world_rank, world_size, new_rank, new_size, color);
21
22// Finalize the new communicator
23MPI_Comm_free(&new_comm);
24
25// Finalize MPI
26MPI_Finalize();
27
28return 0;

Rodando com apenas 4 processos, temos a seguinte saída:

World Rank/Size: 0/4, New Rank/Size: 0/2, Color: 0
World Rank/Size: 1/4, New Rank/Size: 1/2, Color: 0
World Rank/Size: 2/4, New Rank/Size: 0/2, Color: 1
World Rank/Size: 3/4, New Rank/Size: 1/2, Color: 1

3.5.2 MPI_Group

Os grupos são conjuntos de processos que podem ser usados para criar comunicadores.

Exemplo 3.5.2.

O seguinte Código 16 cria dois grupos de processos a partir do grupo do comunicador MPI_COMM_WORLD. O primeiro grupo contém os primeiros np/2 processos e o segundo grupo contém os últimos np/2 processos, onde np é o número de processos inicializados. Em seguida, dois novos comunicadores são criados a partir desses grupos.

Código 16: mpi_group.cpp
1// Initialize MPI
2MPI_Init(nullptr, nullptr);
3
4int world_size;
5MPI_Comm_size(MPI_COMM_WORLD, &world_size);
6int world_rank;
7MPI_Comm_rank(MPI_COMM_WORLD, &world_rank);
8
9// Get the group of the world communicator
10MPI_Group world_group;
11MPI_Comm_group(MPI_COMM_WORLD, &world_group);
12
13// Create a new group for the first half of the ranks
14MPI_Group first_group;
15int ranks[world_size / 2];
16for (int i = 0; i < world_size / 2; ++i) {
17 ranks[i] = i; // Select the first half of the ranks
18}
19MPI_Group_incl(world_group, world_size / 2, ranks, &first_group);
20// Creat a new communicator from the first group
21MPI_Comm first_group_comm;
22MPI_Comm_create(MPI_COMM_WORLD, first_group, &first_group_comm);
23
24
25// Create a new group for the second half of the ranks
26MPI_Group second_group;
27for (int i = world_size / 2; i < world_size; ++i) {
28 ranks[i - world_size / 2] = i; // Select the second half of the ranks
29}
30MPI_Group_incl(world_group, world_size - world_size / 2, ranks, &second_group);
31// Create a new communicator from the second group
32MPI_Comm second_group_comm;
33MPI_Comm_create(MPI_COMM_WORLD, second_group, &second_group_comm);
34
35// Check if the communicators were created successfully
36int group_rank, group_size;
37if (first_group_comm != MPI_COMM_NULL) {
38
39 MPI_Comm_rank(first_group_comm, &group_rank);
40 MPI_Comm_size(first_group_comm, &group_size);
41
42 printf("World rank/size: %d/%d, First group rank/size: %d/%d\n",
43 world_rank, world_size, group_rank, group_size);
44
45} else if (second_group_comm != MPI_COMM_NULL) {
46
47 MPI_Comm_rank(second_group_comm, &group_rank);
48 MPI_Comm_size(second_group_comm, &group_size);
49
50 printf("World rank/size: %d/%d, Second group rank/size: %d/%d\n",
51 world_rank, world_size, group_rank, group_size);
52
53} else {
54 std::cout << "No new communicator created for rank " << world_rank << std::endl;
55}
56
57// Finalize the new communicator
58if (first_group_comm != MPI_COMM_NULL) {
59 MPI_Group_free(&first_group);
60 MPI_Comm_free(&first_group_comm);
61} else if (second_group_comm != MPI_COMM_NULL) {
62 MPI_Group_free(&second_group);
63 MPI_Comm_free(&second_group_comm);
64}
65
66// Finalize MPI
67MPI_Finalize();
68
69return 0;

Rodando com apenas 4 processos, temos a seguinte saída:

World rank/size: 0/4, First group rank/size: 0/2
World rank/size: 1/4, First group rank/size: 1/2
World rank/size: 2/4, Second group rank/size: 0/2
World rank/size: 3/4, Second group rank/size: 1/2

3.5.3 Exercícios

Em construção


Envie seu comentário

Aproveito para agradecer a todas/os que de forma assídua ou esporádica contribuem enviando correções, sugestões e críticas!

Opcional. Preencha seu nome para que eu possa lhe contatar.
Opcional. Preencha seu e-mail para que eu possa lhe contatar.
As informações preenchidas são enviadas por e-mail para o desenvolvedor do site e tratadas de forma privada. Consulte a política de uso de dados para mais informações.

Licença Creative Commons
Este texto é disponibilizado nos termos da Licença Creative Commons Atribuição-CompartilhaIgual 4.0 Internacional. Ícones e elementos gráficos podem estar sujeitos a condições adicionais.

Computação Paralela com C++

Ajude a manter o site livre, gratuito e sem propagandas. Colabore!

3.5 Grupos e comunicadores

Em construção

Comunicadores são objetos que definem grupos de processos que podem se comunicar entre si. Cada comunicador é associado a um grupo de processos, e as operações de comunicação são realizadas dentro desse grupo.

3.5.1 MPI_Comm_Split

Uma das funções mais comumente empregadas para criar um novo comunicador é a MPI_Comm_split. Sua sintaxe é a seguinte:

1int MPI_Comm_split(
2 MPI_Comm comm,
3 int color,
4 int key,
5 MPI_Comm *newcomm)

O argumento comm é o comunicador original (por exemplo, MPI_COMM_WORLD), color é um inteiro que define a cor do grupo de processos que serão incluídos no novo comunicador. Todos os processos que passam pelo mesmo valor de color são atribuídos aos mesmo comunicador. Se color == MPI_UNDEFINED, o processo não é atribuído a nenhum novo comunicador. E, key é um inteiro que define a ordem dos processos no novo comunicador. O processo que passa com o menor valor de key será o rank == 0 no novo comunicador, o próximo com menor valor será o rank == 1 e assim por diante. O argumento newcomm é um ponteiro para o novo comunicador criado.

Exemplo 3.5.1.

O seguinte Código 15 cria dois grupos de processos, um com color == 0 e outro com color == 1. Os processos são distribuídos dois-a-dois entre os comunicadores. Consulte a Figura 3.7.

Refer to caption
Figura 3.7: Criação de novos comunicadores com MPI_Comm_split.
Código 15: comm_split.cpp
1// Initialize MPI
2MPI_Init(nullptr, nullptr);
3
4int world_size;
5MPI_Comm_size(MPI_COMM_WORLD, &world_size);
6int world_rank;
7MPI_Comm_rank(MPI_COMM_WORLD, &world_rank);
8
9// create a new communicator
10int color = world_rank / 2;
11
12MPI_Comm new_comm;
13MPI_Comm_split(MPI_COMM_WORLD, color, world_rank, &new_comm);
14
15int new_rank, new_size;
16MPI_Comm_rank(new_comm, &new_rank);
17MPI_Comm_size(new_comm, &new_size);
18
19printf("World Rank/Size: %d/%d, New Rank/Size: %d/%d, Color: %d\n",
20 world_rank, world_size, new_rank, new_size, color);
21
22// Finalize the new communicator
23MPI_Comm_free(&new_comm);
24
25// Finalize MPI
26MPI_Finalize();
27
28return 0;

Rodando com apenas 4 processos, temos a seguinte saída:

World Rank/Size: 0/4, New Rank/Size: 0/2, Color: 0
World Rank/Size: 1/4, New Rank/Size: 1/2, Color: 0
World Rank/Size: 2/4, New Rank/Size: 0/2, Color: 1
World Rank/Size: 3/4, New Rank/Size: 1/2, Color: 1

3.5.2 MPI_Group

Os grupos são conjuntos de processos que podem ser usados para criar comunicadores.

Exemplo 3.5.2.

O seguinte Código 16 cria dois grupos de processos a partir do grupo do comunicador MPI_COMM_WORLD. O primeiro grupo contém os primeiros np/2 processos e o segundo grupo contém os últimos np/2 processos, onde np é o número de processos inicializados. Em seguida, dois novos comunicadores são criados a partir desses grupos.

Código 16: mpi_group.cpp
1// Initialize MPI
2MPI_Init(nullptr, nullptr);
3
4int world_size;
5MPI_Comm_size(MPI_COMM_WORLD, &world_size);
6int world_rank;
7MPI_Comm_rank(MPI_COMM_WORLD, &world_rank);
8
9// Get the group of the world communicator
10MPI_Group world_group;
11MPI_Comm_group(MPI_COMM_WORLD, &world_group);
12
13// Create a new group for the first half of the ranks
14MPI_Group first_group;
15int ranks[world_size / 2];
16for (int i = 0; i < world_size / 2; ++i) {
17 ranks[i] = i; // Select the first half of the ranks
18}
19MPI_Group_incl(world_group, world_size / 2, ranks, &first_group);
20// Creat a new communicator from the first group
21MPI_Comm first_group_comm;
22MPI_Comm_create(MPI_COMM_WORLD, first_group, &first_group_comm);
23
24
25// Create a new group for the second half of the ranks
26MPI_Group second_group;
27for (int i = world_size / 2; i < world_size; ++i) {
28 ranks[i - world_size / 2] = i; // Select the second half of the ranks
29}
30MPI_Group_incl(world_group, world_size - world_size / 2, ranks, &second_group);
31// Create a new communicator from the second group
32MPI_Comm second_group_comm;
33MPI_Comm_create(MPI_COMM_WORLD, second_group, &second_group_comm);
34
35// Check if the communicators were created successfully
36int group_rank, group_size;
37if (first_group_comm != MPI_COMM_NULL) {
38
39 MPI_Comm_rank(first_group_comm, &group_rank);
40 MPI_Comm_size(first_group_comm, &group_size);
41
42 printf("World rank/size: %d/%d, First group rank/size: %d/%d\n",
43 world_rank, world_size, group_rank, group_size);
44
45} else if (second_group_comm != MPI_COMM_NULL) {
46
47 MPI_Comm_rank(second_group_comm, &group_rank);
48 MPI_Comm_size(second_group_comm, &group_size);
49
50 printf("World rank/size: %d/%d, Second group rank/size: %d/%d\n",
51 world_rank, world_size, group_rank, group_size);
52
53} else {
54 std::cout << "No new communicator created for rank " << world_rank << std::endl;
55}
56
57// Finalize the new communicator
58if (first_group_comm != MPI_COMM_NULL) {
59 MPI_Group_free(&first_group);
60 MPI_Comm_free(&first_group_comm);
61} else if (second_group_comm != MPI_COMM_NULL) {
62 MPI_Group_free(&second_group);
63 MPI_Comm_free(&second_group_comm);
64}
65
66// Finalize MPI
67MPI_Finalize();
68
69return 0;

Rodando com apenas 4 processos, temos a seguinte saída:

World rank/size: 0/4, First group rank/size: 0/2
World rank/size: 1/4, First group rank/size: 1/2
World rank/size: 2/4, Second group rank/size: 0/2
World rank/size: 3/4, Second group rank/size: 1/2

3.5.3 Exercícios

Em construção


Envie seu comentário

Aproveito para agradecer a todas/os que de forma assídua ou esporádica contribuem enviando correções, sugestões e críticas!

Opcional. Preencha seu nome para que eu possa lhe contatar.
Opcional. Preencha seu e-mail para que eu possa lhe contatar.
As informações preenchidas são enviadas por e-mail para o desenvolvedor do site e tratadas de forma privada. Consulte a política de uso de dados para mais informações.

Licença Creative Commons
Este texto é disponibilizado nos termos da Licença Creative Commons Atribuição-CompartilhaIgual 4.0 Internacional. Ícones e elementos gráficos podem estar sujeitos a condições adicionais.

Pedro H A Konzen
| | | |