slides7 - Universidad de Santiago de Chile

Anuncio
Taller de Programación Paralela
Fernando R. Rannou
Departamento de Ingenierı́a Informática
Universidad de Santiago de Chile
July 18, 2008
MPI 2
MPI 2
Comunicadores y grupos (1)
MPI 2
■
Un comunicador se compone de:
1. un grupo de procesos
colección ordenada de procesos
2. un contexto
objeto definido por el sistema que identifica univocamente al comunicador
■
En MPI existe
1. intra-comunicadores: colección de procesos que se pueden comunicar
mediante el envı́o y recepción de mensajes, ya sea punto-a-punto y
colectivamente
2. inter-comunicadores: objetos que permiten que procesos de
intra-comunicadores diferentes se comuniquen
Fernando R. Rannou
Diinf-USACH
3 / 24
Comunicadores y grupos (2)
MPI 2
■
Un proceso puede pertenecer a más de un grupo/comunicador
■
Para el programador, grupo y comunicador es una misma cosa.
■
Permite al programador organizar las tareas en grupos de tareas
■
Permite operaciones de comunicación colectiva sobre un subconjunto de tareas
relacionadas
■
Forman la base para crear topologı́as virtuales
Fernando R. Rannou
Diinf-USACH
4 / 24
Creación de comunicadores
MPI 2
■
MPI permite crear nuevos comunicadores consistente de un sub-grupo de
procesos
■
Las etapas son:
1. Identificar el sub-grupo de procesos
2. Crear el nuevo grupo (vacı́o)
3. Crear el nuevo comunicador
Fernando R. Rannou
Diinf-USACH
5 / 24
Grupos y comunicadores
MPI 2
Fernando R. Rannou
Diinf-USACH
6 / 24
Creación de comunicadores (cont)
MPI 2
int MPI_Comm_group(MPI_Comm comm, MPI_Group *group);
■
Retorna el grupo group asociado a un comunicador comm
int MPI_Group_incl(MPI_Group old_group, int new_group_size,
int ranks_in_old_group[], MPI_Group *new_group);
■
Incluye los procesos con ranks ranks in old group[] del antiguo grupo, en
un nuevo grupo new group
int MPI_Comm_create(MPI_Comm old_comm, MPI_Group new_group,
MPI_Comm *new_comm);
■
Crea un nuevo comunicador new comm con el grupo de procesos new group
Fernando R. Rannou
Diinf-USACH
7 / 24
Ejemplo 1
MPI 2
MPI_Group world_group, firstrow_group;
MPI_Comm
firstrow_comm;
int
*ranks;
...
ranks = (int *) malloc(sizeof(int)*q); // q es largo de la fila
for (i=0; i < q; i++) ranks[i] = i;
MPI_Comm_group(MPI_COMM_WORLD, &world_group);
MPI_Group_incl(world_group, q, ranks, &firstrow_group);
MPI_Comm_create(MPI_COMM_WORLD, firstrow_group, &firstrow_comm);
...
0
1
8
5
10
9
4
2
2
1
0
3
3
6
firstrow_comm
7
11
MPI_COMM_WORLD
Fernando R. Rannou
Diinf-USACH
8 / 24
Ejemplo 2
MPI 2
1
2
3
ranks1 [4]={0 ,1 ,2 ,3} , ranks2 [4]={4 ,5 ,6 ,7};
MPI_Group orig_group , new_group ;
MPI_Comm
new_comm ;
4
5
6
7
MPI_Init (& argc ,& argv ) ;
MPI_Comm_rank ( MPI_COMM_WORLD , & rank ) ;
MPI_Comm_size ( MPI_COMM_WORLD , & numtasks ) ;
8
9
10
sendbuf = rank ;
MPI_Comm_group ( MPI_COMM_WORLD , & orig_group ) ;
11
12
13
14
15
if ( rank < 4)
MPI_Group_incl ( orig_group , 4 , ranks1 , & new_group ) ;
else
MPI_Group_incl ( orig_group , 4 , ranks2 , & new_group ) ;
16
17
18
MPI_Comm_create ( MPI_COMM_WORLD , new_group , & new_comm ) ;
MPI_Allreduce (& sendbuf , & recvbuf , 1 , MPI_INT , MPI_SUM , new_comm
);
19
MPI_Group_rank ( new_group , & new_rank ) ;
21
printf ( " rank = % d newrank = % d recvbuf = % d \ n " , rank , new_rank ,
recvbuf ) ;
Fernando R. Rannou
20
Diinf-USACH
9 / 24
Particionando comunicadores
MPI 2
■
El procedimiento anterior es muy tedioso, por ejemplo, en el caso que
tuvieramos que crear un comunicador para cada fila de una matrix de 100 × 100
■
Con MPI Comm split() podemos crear múltiples comunicadores
int MPI_Comm_split(MPI_Comm old_comm, int split_key, int rank_key,
MPI_Comm *new_comm);
■
Crea un nuevo comunicador para cada valor de split key.
■
Los procesos que invocan MPI Comm split() con la misma llave split key
forman un nuevo grupo y comunicador
■
rank key define el nuevo rango en el nuevo comunicador: sean A y B dos
procesos con el mismo split key:
1. si rank key de A es menor que rank key de B, entonces el rango de A
será menor que el rango de B en el nuevo comunicador
2. Si ambos procesos tienen el mismo rank key, el sistema asignará rangos
arbitrarios.
Fernando R. Rannou
Diinf-USACH
10 / 24
Ejemplo MPI Comm split()
MPI 2
Supongamos que deseamos crear un comunicador para cada fila del ejemplo 1 anterior
MPI_Comm
row_comm;
int
row;
...
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
row = rank/q;
MPI_Comm_split(MPI_COMM_WORLD, row, rank, &row_comm);
0
0/0
1
2/2
8
5
3/3
0/4
1/5
2/6
3/7
10
9
4
1/1
2
3
0/8
1/9
2/10
3/11
6
7
11
MPI_COMM_WORLD
Fernando R. Rannou
Diinf-USACH
11 / 24
Topologı́as
MPI 2
1. Una topologı́a virtual describe un mapeo/ordenamiento sobre los procesos en
una forma geométrica.
2. Una topologı́a se construye a partir de los grupos y comunicadores
3. Por ejemplo, si la aplicación involucra comunicación de procesos vecinos, como
lo muestra la figura, serı́a mejor crear una topologı́a ad-hoc
4. Sin embargo, la topologı́a no restringe que un proceso se comunique con otro
dentro de su comunicador
Fernando R. Rannou
Diinf-USACH
12 / 24
Topologı́as Cartesianas y de grafos
MPI 2
■
MPI permite la definición de topologı́a de tipo Cartesiano, en la que los
procesos se ordenan con una estructura regular (cı́clica o no)
■
MPI también permite topologı́as generales o de grafos como la siguiente figura
■
Nosotros sólo veremos topologı́as Cartesianas
0
1
Fernando R. Rannou
Diinf-USACH
2
3
4
13 / 24
Topologı́as Cartesianas
MPI 2
int MPI_Cart_create(MPI_Comm old_comm, int number_of_dims, int dim_sizes[],
int wrap_around[], int reorder, MPI_comm *new_comm);
■
A partir del comunicador old comm, MPI Cart create() crea un nuevo
comunicador, new comm, donde los procesos se estructuran en una grilla de
number of dims dimensiones.
■
El tamaño de cada dimensión es especificada en el arreglo dim size[]
■
El arreglo wrap around[] especifica si la dimensión es lineal o circular:
◆ wrap around[i] = 1 → dimensión i es circular
◆ wrap around[i] = 0 → dimensión i es lineal
■
reorder especifica si los ranks de los procesos deben o no permanecer igual
◆ reorder = 0 → usar los mismos ranks
◆ reorder = 1 → reordenar
Fernando R. Rannou
Diinf-USACH
14 / 24
Ejemplo con MPI Cart create()
MPI 2
MPI_comm my_2Dcomm;
...
int dim_sizes[3];
dim_sizes[0] = 2; wrap_around[0] =
dim_sizes[1] = 3; wrap_around[1] =
dim_sizes[2] = 3; wrap_around[2] =
MPI_Cart_create(MPI_COMM_WORLD, 3,
...
0;
0;
1;
dim_sizes, wrap_around, 1, &my_2Dcomm);
■
Crea una grilla de 2 × 3 × 3, que es circular sólo en la dimensión 3.
■
Los nuevos ranks son asignados en orden row mayor
■
MPI Cart create() es una operación colectiva
12
6
Fernando R. Rannou
Diinf-USACH
13
14
8
7
0
1
2
3
4
5
17
11
15 / 24
Coordenadas a partir del rank
MPI 2
■
Para obtener el rank en el nuevo comunicador, simplemente invocamos
MPI Comm rank()
■
Si deseamos obtener las “coordenadas” del proceso (posición Cartesiana en la
grilla), invocamos MPI Cart coords()
int MPI_Cart_coords(MPI_Comm comm, int rank, int number_of_dims,
int coordinates[]);
■
coordinates[] es una arreglo de largo number of dims tal que
coordinates[i] es la posición en la dimensión i
■
Note que para obtener las coordenas, primero debemos conocer el rank
■
¿Qué pasarı́a si las coordenas están fuera de la grilla?
Fernando R. Rannou
Diinf-USACH
16 / 24
Ranks a partir de coordenadas
MPI 2
■
Si deseamos saber el rank del proceso en una cierta posición en la grilla,
llamamos
int MPI_Cart_rank(MPI_Comm comm, int coordinates[], int *rank);
■
Tanto MPI Cart coords() como MPI Cart rank() son funciones locales.
■
No confundir MPI Comm rank() con MPI Cart rank()
Fernando R. Rannou
Diinf-USACH
17 / 24
MPI Cart shift()
MPI 2
int MPI_Cart_shift(MPI_Comm comm, int direction, int displ,
int *source, int *dest )
■
Retorna los rangos de los procesos “vecinos” fuentes (source) y destinos
(dest) que están a una distancia displ en la dirección direction
■
Si la grilla es N dimensional, entonces 0 ≤ direction < N .
■
Un valor displ = 1 indica los vecinos inmediatos
■
Si displ > 0, source es el proceso con menor rango y dest con mayor rango
■
Si displ < 0 se revierte la lógica anterior
Fernando R. Rannou
Diinf-USACH
18 / 24
Ejemplo MPI Cart shift()
MPI 2
Fernando R. Rannou
Diinf-USACH
19 / 24
Creando sub-comunicadores
MPI 2
int MPI_Cart_sub(MPI_Comm cart_comm, int free_coords[], MPI_Comm sub_comm);
■
MPI Cart sub() permite crear nuevos comunicadores para subgrupos de
procesos que ya pertenecen a un comunicador topologı́a grilla
■
Útil para cuando un proceso necesita realizar una operación de recucción sólo
en una fila o columna, o en general en sólo una de las dimensiones
■
free coords[] es un arreglo de booleanos de largo num dim que especifica si
cada dimensión es parte del nuevo comunicador, tal que free coords[i] = 0
si la dimensión i es libre o no, es decir los procesos con la misma dimensión i
pertenecen al mismo comunicador
■
Se crean varios nuevos comunicadores sub comm
Fernando R. Rannou
Diinf-USACH
20 / 24
Ejemplo MPI Cart sub()
MPI 2
■
Ejemplo
0
(0,0)
4
1
(0,1)
2
(0,2)
5
6
(1,1)
(1,2)
3
(0,3)
7
MPI_Comm my_2Dcomm, row_comm;
...
8
9
10
11
(2,0)
(2,1)
(2,2)
(2,3)
int dim_sizes[2];
dim_sizes[0] = 3; wrap_around[0] = 0;
dim_sizes[1] = 4; wrap_around[1] = 1;
MPI_Cart_create(MPI_COMM_WORLD, 2, dim_sizes, wrap_around, 1, &my_2Dcomm);
...
int free_coords[2];
free_coords[0] = 0;
free_coords[1] = 1;
MPI_Cart_sub(my_2Dcomm, free_coords, row_comm);
(1,0)
Fernando R. Rannou
Diinf-USACH
(1,3)
21 / 24
Mensajes compuestos
MPI 2
■
MPI provee tres métodos para agrupar datos escalares en un mensaje:
1. El parámetro count; como el usado en las funciones punto-a-punto y
colectivas para enviar arreglos de enteros o flotantes
2. Tipos de datos derivados; sistema complejo de entender
3. Empaquetamiento de datos; el más fácil
Fernando R. Rannou
Diinf-USACH
22 / 24
Empaquetamiento
MPI 2
■
1
2
3
4
5
6
7
8
9
10
11
12
13
Suponga que un proceso necesita enviar un mensaje compuesto de dos flotantes
(float) y un entero (int) a todos los procesos en su comunicador
float * a ;
float * b ;
int * c ;
...
char buffer [100];
int position ;
if ( myrank == 0) {
position = 0;
MPI_Pack (a , 1 , MPI_FLOAT , buffer , 100 , & position ,
MPI_COMM_WORLD ) ;
MPI_Pack (b , 1 , MPI_FLOAT , buffer , 100 , & position ,
MPI_COMM_WORLD ) ;
MPI_Pack (c , 1 , MPI_INT , buffer , 100 , & position ,
MPI_COMM_WORLD ) ;
MPI_Bcast ( buffer , 100 , MPI_PACKED , 0 , MPI_COMM_WORLD ) ;
} else { ...
Fernando R. Rannou
Diinf-USACH
23 / 24
Desempaquetamiento
MPI 2
1
2
3
4
5
6
7
8
...
else {
MPI_Bcast ( buffer , 100 , MPI_PACKED ,
position = 0;
MPI_Unpack ( buffer , 100 , & position ,
MPI_COMM_WORLD ) ;
MPI_Unpack ( buffer , 100 , & position ,
MPI_COMM_WORLD ) ;
MPI_Unpack ( buffer , 100 , & position ,
MPI_COMM_WORLD ) ;
}
0 , MPI_COMM_WORLD ) ;
a , 1 , MPI_FLOAT ,
b , 1 , MPI_FLOAT ,
c , 1 , MPI_INT ,
int MPI_Pack(void *inbuf, int incount, MPI_Datatype datatype,
void *outbuf, int outcount, int *position, MPI_Comm comm );
int MPI_Unpack(void *inbuf, int insize, int *position,
void *outbuf, int outcount, MPI_Datatype datatype,
MPI_Comm comm);
Fernando R. Rannou
Diinf-USACH
24 / 24
Descargar