Communicators Bibliotecas, topologias, etc. Intra-communicators: entre processos do mesmo communicator Inter-communicators: entre diferentes communicators Rotinas associadas: MPI_Comm_group MPI_Group_incl MPI_Comm_excl MPI_Group_rank MPI_Group_free MPI_Comm_create MPI_Comm_split MPI_Comm_group define o handle para o grupo de processadores int MPI_Comm_group( MPI_Comm comm, MPI_Group *group) typedef int MPI_Group; MPI_Group_incl cria um novo grupo a partir de um grupo já existente especificando os membros do grupo int MPI_Group_incl( MPI_Group old_group, int count, int *members, MPI_Group *new_group ) members[count] define quais os ranks do old_group que pertencem ao new_group MPI_Group_excl cria um novo grupo a partir de um grupo já existente excluindo ranks int MPI_Group_excl( MPI_Group group, int count, int *nonmembers, MPI_Group *new_group ) nonmembers[count] define quais os ranks do group que são excluídos int Neven, Nodd, members[6], even_rank, odd_rank; MPI_Group group_world, even_group, odd_group; MPI_Init(&argc, &argv); MPI_Comm_rank(MPI_COMM_WORLD, &myrank); MPI_Comm_size(MPI_COMM_WORLD, &nproc); Neven = (p + 1)/2; Nodd = p - Neven; members[0] = 2; members[1] = 0; members[2] = 4; MPI_Comm_group(MPI_COMM_WORLD, &group_world); MPI_Group_incl(group_world, Neven, members, &even_group); MPI_Group_excl(group_world, Neven, members, &odd_group); MPI_Group_rank int MPI_Group_rank( MPI_Group group, int *rank) MPI_UNDEFINED se processo não pertencer ao grupo MPI_Group_free int MPI_Group_free(MPI_Group *group) liberta o grupo, mas não o comunicator MPI_Comm_create int MPI_Comm_create( MPI_Comm old_comm, MPI_Group group, MPI_Comm *new_comm ) collective communication; MPI_COMM_NULL se o processo não pertencer ao grupo #include "mpi.h" MPI_Comm comm_world, comm_worker; MPI_Group group_world, group_worker; int ierr; comm_world = MPI_COMM_WORLD; MPI_Comm_group(comm_world, &group_world); MPI_Group_excl(group_world, 1, 0, &group_worker); MPI_Comm_create(comm_world, group_worker, &comm_worker); MPI_Group_free(&group_worker); ... MPI_Comm_free(&comm_worker); Mecanismo que ajusta o padrão das Topologias Virtuais comunicações num communicator Equação de Poisson – decomposição do domínio Código mais simples Y Optimização 0 1 2 3 4 5 6 7 8 9 10 11 X MPI_Cart_create MPI_Cart_coords MPI_Cart_rank MPI_Cart_shift MPI_Cart_sub MPI_Cartdim_get MPI_Cart_get Vamos considerar apenas topologias cartesianas virtuais!!! MPI_Cart_create cria um novo communicator com topologia cartesiana int MPI_Cart_create( MPI_Comm old_comm, int ndims, int *dim_size, int *periods, int reorder, MPI_Comm *new_comm) dim_size[ndims], periods[ndims] > collective blocking communication > MPI_COMM_NULL processos não incluídos no novo communicator MPI_Comm old_comm, new_comm; int ndims, reorder, periods[2], dim_size[2]; old_comm = MPI_COMM_WORLD; ndims = 2; dim_size[0] = 3; /* linhas */ dim_size[1] = 2; /* colunas */ periods[0] = 1; /* condições periódicas nas linhas */ periods[1] = 0; /* não periódicas nas colunas */ reorder = 1; /* permite reordenação para possivel ganho de eficiência MPI_Cart_create(old_comm, ndims, dim_size, periods, reorder, &new_comm); */ P0 (0,0) P1 (0,1) P2 (1,0) P3 (1,1) P4 (2,0) P5 (2,1) dim_size[0] = 3; dim_size[1] = 2; periods[0] = 1; periods[1] = 0; MPI_Cart_coords devolve as correspondentes coordenadas cartesianas de um rank linear int MPI_Cart_coords( MPI_Comm, int rank, int maxdims, int *coords) maxdims = número de dimensões topologia cartesiana coords[ndims] MPI_Cart_rank rank das coordenadas cartesianas numa topologia virtual int MPI_Cart_rank( MPI_Comm comm, int *coords, int *rank ) coords[ndims] MPI_Cart_sub cria um novo communicator para subgrid até dimensão N-1 a partir de uma grid cartesiana de dimensão N int MPI_Cart_sub( MPI_Comm old, int *belongs, MPI_Comm *new) belongs[ndims] = 0 pertence subgrid; 1 não pertence à subgrid comprimento total de cada dimensão é utilizado nas subgrids /* Topologia cartesina 2D */ MPI_Cart_create(MPI_COMM_WORLD, ndim, dims, period, reorder, &comm2D); MPI_Comm_rank(comm2D, &id2D); MPI_Cart_coords(comm2D, id2D, ndim, coords2D); /* subgrid 1D linha */ belongs[0] = 0; belongs[1] = 1; MPI_Cart_sub(comm2D, belongs, &commrow); /* subrgid 1D coluna */ belongs[0] = 1; belongs[1] = 0; MPI_Cart_sub(comm2D, belongs, &commcol); MPI_Cartdim_get determina o número de dimensões de uma subgrid int MPI_Cartdim_get( MPI_Comm comm, int *ndims ) /* subgrids columna */ belongs[0] = 1; belongs[1] = 0; MPI_Cart_sub(grid_comm, belongs, &col_comm); /* número de dimensões de uma grid cartesiana */ MPI_Cartdim_get(col_comm, &ndims); MPI_Cart_shift determina os ranks fonte e destino, para uma certo deslocamento (displ), numa certa direcção int MPI_Cart_shift( MPI_Comm comm, int direction, int displ, int *source, int *dest ) 0 1 2 3 4 5 6 7 8 9 10 11 /* create Cartesian topology for processes */ dims[0] = nrow; /* number of rows */ dims[1] = mcol; /* number of columns */ period[0] = 1; /* cyclic in this direction */ period[1] = 0; /* no cyclic in this direction */ MPI_Cart_create(MPI_COMM_WORLD, ndim, dims, period, reorder, &comm2D); MPI_Comm_rank(comm2D, &me); MPI_Cart_coords(comm2D, me, ndim, coords); index = 0; /* shift along the 1st index (out of 2) */ displ = 1; /* shift by 1 */ MPI_Cart_shift(comm2D, index, displ, &source, &dest1);