Задача состоит в широковещательной передаче от чётных процессов своих номеров нечётным процессам. Как я задумал реализацию:
- Создаю группы вида 1 чётный + все нечётные (0,1,3,5), (2,1,3,5);
- Создаю для них коммуникаторы;
- Использую Broadcast в коммуникаторах.
Первые два пункта сделал, вроде бы. На бродкасте застрял. Похоже ранги созданных коммуникаторов не перебираются (rank_in_comm). Да и Invalid root в MPI_Bcast.
#include "mpi.h"
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
int rank, rank_in_comm, size, odd_count, *ranks, msg, i, j;
MPI_Status status;
MPI_Group world_group, *groups, group;
MPI_Comm *comms, empty_comm;
MPI_Init(&argc, &argv);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
MPI_Comm_size(MPI_COMM_WORLD, &size);
MPI_Comm_group(MPI_COMM_WORLD, &world_group);
// Odd array for making a group
for (i = 0; i < size; i++)
if (i % 2 != 0) odd_count++;
ranks = (int*)calloc(odd_count + 1, sizeof(int));
for (i = 1, j = 0; i < size; i += 2, j++)
{
ranks[i - j] = i;
// printf("%d ", ranks[i - j]);
}
// printf("\n");
// Allocating memory for groups & communicators
groups = (MPI_Group*)calloc(size - odd_count, sizeof(MPI_Group));
comms = (MPI_Comm*)calloc(size - odd_count + 1, sizeof(MPI_Comm));
if (rank % 2 == 0)
{
ranks[0] = rank;
printf("Group %d: ", rank);
for (i = 0; i <= odd_count; i++)
printf("%d ", ranks[i]);
printf("\n");
MPI_Group_incl(world_group, odd_count + 1, ranks, &groups[rank]);
// if (groups[rank]) printf("+ group\n");
MPI_Comm_create(MPI_COMM_WORLD, groups[rank], &comms[rank]);
}
else MPI_Comm_create(MPI_COMM_WORLD, MPI_GROUP_EMPTY, &empty_comm);
// if (empty_comm) printf("+ comm\n");
if (comms[rank])
{
MPI_Comm_rank(comms[rank], &rank_in_comm);
if (rank_in_comm % 2 == 0)
{
// printf("%d ",rank_in_comm);
// printf("%d ",rank);
msg = rank;
MPI_Bcast(&msg, 1, MPI_INT, rank, comms[rank]);
printf("%d sended its rank\n", rank);
}
else
{
MPI_Bcast(&msg, 1, MPI_INT, msg, comms[rank]);
printf("%d received %d\n", rank, msg);
}
}
//MPI_Comm_free(comms[]);
//MPI_Group_free(groups[]);
free(ranks);
MPI_Finalize();
return 0;
}
Потом переделал:
- Создаю группу с нечётными номерами;
- Добавляю её в коммуникатор;
- Создаю группу для 1 чётного номера;
- Объединяю обе группы;
- Шлю бродкаст внутри коммуникатора.
Но и тут тоже что-то неверно. Invalid communicator в MPI_Bcast.
#include "mpi.h"
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
int rank, rank_in_comm, size, odd_count, *ranks, msg, i, j, single_p[1];
MPI_Group world_group, group, s_group;
MPI_Comm comm;
MPI_Init(&argc, &argv);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
MPI_Comm_size(MPI_COMM_WORLD, &size);
MPI_Comm_group(MPI_COMM_WORLD, &world_group);
// Odd array for making a group
for (i = 0; i < size; i++)
if (i % 2 != 0) odd_count++;
ranks = (int*)calloc(odd_count, sizeof(int));
for (i = 1, j = 1; i < size; i += 2, j++)
{
ranks[i - j] = i;
// printf("%d ", ranks[i - j]);
}
// printf("\n");
printf("Process %d odd group: ", rank);
for (i = 0; i < odd_count; i++)
printf("%d ", ranks[i]);
printf("\n");
MPI_Group_incl(world_group, odd_count, ranks, &group);
MPI_Comm_create(MPI_COMM_WORLD, group, &comm);
if (rank % 2 == 0)
{
single_p[1] = rank;
MPI_Group_incl(world_group, 1, &single_p[1], &s_group);
MPI_Group_union(s_group, group, &group);
MPI_Group_size(group, &size);
printf("Group size: %d\n", size);
MPI_Group_rank(group, &rank_in_comm);
int root = rank; printf("Root: %d, Rank in comm: %d\n", root, rank_in_comm);
if (rank_in_comm % 2 == 0)
{
msg = rank;
MPI_Bcast(&msg, 1, MPI_INT, root, comm);
printf("%d sended its rank\n", rank_in_comm);
}
else
{
MPI_Bcast(&msg, 1, MPI_INT, root, comm);
printf("%d received %d\n", rank_in_comm, msg);
}
// MPI_Group_excl(group, 1, &single_p[1], &group);
// MPI_Comm_free(&comm);
// MPI_Group_free(&group);
}
free(ranks);
MPI_Finalize();
return 0;
}
Кто-нибудь может помочь разобраться?