Его можно разделить больший коммуникатор на более мелкие коммуникаторы некоторых предпочтительного размера:
#include <mpi.h>
#include <stdio.h>
int main(int argc, char** argv) {
// Initialize the MPI environment
MPI_Init(NULL, NULL);
// Get the rank and size in the MPI_COMM_WORLD communicator
int world_rank, world_size;
MPI_Comm_rank(MPI_COMM_WORLD, &world_rank);
MPI_Comm_size(MPI_COMM_WORLD, &world_size);
int color = world_rank/4; //4 process (colors) for each communicator
MPI_Comm row_comm;
/*
The first argument is the communicator that will be used as the basis for the new communicators.
The second argument determines to which new communicator each processes will belong.
The third argument determines the ordering (rank) within each new communicator...
The process which passes in the smallest value for the third argument will be rank 0, the next smallest will be rank 1, and so on.
The final argument returns the new communicator back to the user.
*/
MPI_Comm_split(MPI_COMM_WORLD, color, world_rank, &row_comm);
int row_rank, row_size;
MPI_Comm_rank(row_comm, &row_rank);
MPI_Comm_size(row_comm, &row_size);
printf("WORLD RANK/SIZE: %d/%d \t ROW RANK/SIZE: %d/%d\n",
world_rank, world_size, row_rank, row_size);
MPI_Comm_free(&row_comm);
// Finalize the MPI environment.
MPI_Finalize();
}
Или вы можете создавать группы (более гибкий способ)
#include <mpi.h>
#include <stdio.h>
int main(int argc, char** argv) {
// Initialize the MPI environment
MPI_Init(NULL, NULL);
// Get the rank and size in the original communicator
int world_rank, world_size;
MPI_Comm_rank(MPI_COMM_WORLD, &world_rank);
MPI_Comm_size(MPI_COMM_WORLD, &world_size);
// Get the group of processes in MPI_COMM_WORLD
MPI_Group world_group;
MPI_Comm_group(MPI_COMM_WORLD, &world_group);
int prime_group_size = 6;
const int ranks[6] = {2, 3, 5, 7, 11, 13};
// Construct a group containing all of the prime ranks in world_group
MPI_Group prime_group;
MPI_Group_incl(world_group, prime_group_size, ranks, &prime_group);
// Create a new communicator based on the group
MPI_Comm prime_comm;
MPI_Comm_create_group(MPI_COMM_WORLD, prime_group, 0, &prime_comm);
int prime_rank = -1, prime_size = -1;
// If this rank isn't in the new communicator, it will be
// MPI_COMM_NULL. Using MPI_COMM_NULL for MPI_Comm_rank or
// MPI_Comm_size is erroneous
if (MPI_COMM_NULL != prime_comm) {
MPI_Comm_rank(prime_comm, &prime_rank);
MPI_Comm_size(prime_comm, &prime_size);
printf("WORLD RANK/SIZE: %d/%d \t PRIME RANK/SIZE: %d/%d\n",
world_rank, world_size, prime_rank, prime_size);
MPI_Group_free(&prime_group);
MPI_Comm_free(&prime_comm);
}
MPI_Group_free(&world_group);
// Finalize the MPI environment.
MPI_Finalize();
}
REFERENCE
Спасибо! Второй пример - то, что мне нужно. MPI_Comm_split не будет работать для меня. Мне интересно о вызовах MPI_Group_incl и MPI_Comm_create. Нужно ли всем процессам совершать эти звонки? У меня будет несколько коммуникаторов. Могу ли я написать код, чтобы для конкретного коммуникатора только обработчики этого коммуникатора совершали вызовы для этого коммуникатора? Еще раз спасибо. –
Вы можете использовать некоторую структуру, такую как MAP, в сочетании с условными выражениями, чтобы сделать выбранный набор процессов выполненными вами вызовами. Что-то вроде: if (can_read_file_A [world_rank] == true) {... создать определенную группу, коммуникаторы, запустить код и освободить память ...} – Felipe