La Interfaz de Paso de Mensajes: MPI. - Departamento de ...
La Interfaz de Paso de Mensajes: MPI. - Departamento de ...
La Interfaz de Paso de Mensajes: MPI. - Departamento de ...
Create successful ePaper yourself
Turn your PDF publications into a flip-book with our unique Google optimized e-Paper software.
Introducción a la <strong>Interfaz</strong><strong>de</strong> paso <strong>de</strong> mensajes (<strong>MPI</strong>)<strong>MPI</strong> communicator 1P0value<strong>MPI</strong> communicator 2 0 1P1P2value2 3P3José Miguel Mantas RuizDepto. <strong>de</strong> Lenguajes y Sistemas InformáticosUniversidad <strong>de</strong> Granada
Contenido1. Message Passing Interface (<strong>MPI</strong>)2. Funciones <strong>MPI</strong> básicas3. Envío y recepción simultánea4. Operaciones <strong>de</strong> comunicación colectiva5. Comunicación No bloqueante6. Comunicadores7. Topologías Cartesianas8. Tipos <strong>de</strong> datos <strong>de</strong>rivados y Empaquetado9. Referencias útiles
1. Message Passing Interface (<strong>MPI</strong>)• Funciones para paso <strong>de</strong> mensajes y operaciones. complementarias (>120rutinas con numerosos parámetros y variantes).• “<strong>Interfaz</strong>” estándar para C y Fortran con diversas implementaciones.• Objetivo diseño: paso <strong>de</strong> mensajes portable y fácil <strong>de</strong> usar.• Basta con un pequeño subconjunto <strong>de</strong> <strong>MPI</strong>.• Mo<strong>de</strong>lo <strong>de</strong> Programación en <strong>MPI</strong>:– Computación ⇒ Número fijado <strong>de</strong> procesos se comunican mediante llamadasa funciones <strong>de</strong> envío y recepción <strong>de</strong> mensajes.– Mo<strong>de</strong>lo básico: SPMD– Extensión: cada proceso pue<strong>de</strong> ejecutar diferentes programas → MPMD• Creación e inicialización <strong>de</strong> procesos– No <strong>de</strong>finido en el estándar: <strong>de</strong>pen<strong>de</strong> implementación.– En mpich: mpirun prog1 –machinefile maquinas –np 4• Comienza 4 copias <strong>de</strong>l ejecutable “prog1”.• <strong>La</strong> asignación <strong>de</strong> procesos a máquinas se <strong>de</strong>fine en el archivo “maquinas”.
1. Message Passing Interface (<strong>MPI</strong>)1.1. Asuntos <strong>de</strong> implementación• #inclu<strong>de</strong> "mpi.h“– Define ctes, tipos <strong>de</strong> datos y los prototipos <strong>de</strong> las funciones <strong>MPI</strong>• Funciones <strong>de</strong>vuelven código <strong>de</strong> error– <strong>MPI</strong>_SUCCESS ⇒ Ejecución correcta• <strong>MPI</strong>_Status: estructura con 2 campos:– status.<strong>MPI</strong>_SOURCE: proceso fuente– status.<strong>MPI</strong>_TAG: etiqueta <strong>de</strong>l mensaje.• Tipos <strong>de</strong> datos <strong>MPI</strong>– <strong>MPI</strong>_CHAR, <strong>MPI</strong>_INT, <strong>MPI</strong>_LONG, <strong>MPI</strong>_UNSIGNED_CHAR,<strong>MPI</strong>_UNSIGNED, <strong>MPI</strong>_UNSIGNED_LONG, <strong>MPI</strong>_FLOAT, <strong>MPI</strong>_DOUBLE,<strong>MPI</strong>_LONG_DOUBLE, etc.• Comunicador= Grupos <strong>de</strong> procesos + contexto
2. Funciones <strong>MPI</strong> básicas• <strong>MPI</strong>_INIT :• <strong>MPI</strong>_FINALIZE :• <strong>MPI</strong>_COMM_SIZE :• <strong>MPI</strong>_COMM_RANK:• <strong>MPI</strong>_SEND :• <strong>MPI</strong>_RECV :Inicializa entorno <strong>de</strong> ejecución <strong>MPI</strong>.Finaliza entorno <strong>de</strong> ejecución <strong>MPI</strong>.Determina nº procesos <strong>de</strong>l comunicador.Determina id. proceso en el comunicador.Envío básico mensaje.Recepción básica mensaje.2.1. Iniciando y finalizando <strong>MPI</strong>• int <strong>MPI</strong>_Init (int *argc, char ***argv)– Llamado antes <strong>de</strong> cualquier otra función <strong>MPI</strong>– Llamar más <strong>de</strong> una vez durante ejecución ⇒ Error– Argumentos argc, argv: Argumentos <strong>de</strong> la línea <strong>de</strong> or<strong>de</strong>n <strong>de</strong>l progr.• int <strong>MPI</strong>_Finalize ( )– Llamado al fin <strong>de</strong> la computación: Tareas <strong>de</strong> limpieza para finalizarentorno <strong>de</strong> ejecución
2. Funciones <strong>MPI</strong> básicas2.2. Introducción a los Comunicadores• Comunicador = variable <strong>de</strong> tipo <strong>MPI</strong>_Comm = Grupo_procs + Contexto– Grupo <strong>de</strong> procesos: Subconjunto <strong>de</strong> procesos– Contexto <strong>de</strong> comunicación: Ámbito <strong>de</strong> paso <strong>de</strong> mensajes en el que secomunican dichos procesos. Un mensaje enviado en un contexto sólo se conoce enese contexto ⇒ elemento <strong>de</strong>l “sobre” <strong>de</strong>l mensaje.• Argumento en funciones <strong>de</strong> transferencia.• <strong>MPI</strong>_COMM_WORLD : Comunicador <strong>MPI</strong> por <strong>de</strong>fecto– Incluye todos los procesos en ejecución<strong>MPI</strong>_COMM_WORLDP0 P1 P2 P3 P4 P5comm1P6 P7 P8 P9 P10 P11
2. Funciones <strong>MPI</strong> básicas2.2. Introducción a los Comunicadores (cont.)• I<strong>de</strong>ntificación unívoca <strong>de</strong> procesos participantes en comunicador– Un proceso pue<strong>de</strong> pertenecer a diferentes comunicadores– Cada proceso tiene un i<strong>de</strong>ntificador: <strong>de</strong>s<strong>de</strong> 0 a size_comm-1– <strong>Mensajes</strong> <strong>de</strong>stinados a diferentes contextos <strong>de</strong> comunicación nointerfieren entre sí.comm1<strong>MPI</strong>_COMM_WORLDcomm1P0 P1 P2 P3 P4 P5P0P1P6 P7 P8 P9 P10 P11P2P3
2. Funciones <strong>MPI</strong> básicas2.3. Obteniendo Informaciónint <strong>MPI</strong>_Comm_size ( <strong>MPI</strong>_Comm comm, int *size )– size= nº <strong>de</strong> procs que pertenecen al comunicador comm.– Ej.: <strong>MPI</strong>_Comm_size ( <strong>MPI</strong>_COMM_WORLD, &size) ⇒ size = nº total <strong>de</strong> procs.int <strong>MPI</strong>_Comm_rank ( <strong>MPI</strong>_Comm comm, int *rank )– rank= I<strong>de</strong>ntificador <strong>de</strong>l proceso llamador en comm.#inclu<strong>de</strong> #inclu<strong>de</strong> "mpi.h"int main(int argc, char **argv ) {int rank, size;<strong>MPI</strong>_Init( &argc, &argv );<strong>MPI</strong>_Comm_size( <strong>MPI</strong>_COMM_WORLD, &size );<strong>MPI</strong>_Comm_rank( <strong>MPI</strong>_COMM_WORLD, &rank );printf( "Hello world from process %d of %d\n", rank, size );<strong>MPI</strong>_Finalize( ); return 0;}% mpicc -o helloworld helloworld.c% mpirun -np 4 helloworldHello world from process 0 of 4Hello world from process 3 of 4Hello world from process 1 of 4Hello world from process 2 of 4
2. Funciones <strong>MPI</strong> básicas2.4. Envío y recepción <strong>de</strong> mensajesint <strong>MPI</strong>_Send ( void *buf, int count, <strong>MPI</strong>_Datatype datatype, int <strong>de</strong>st, int tag,<strong>MPI</strong>_Comm comm )– Envía datos almacenados en buffer (count elem. <strong>de</strong> tipo datatype) apuntado porbuf al proc. <strong>de</strong>st con la etiqueta tag (entero >0) <strong>de</strong>ntro <strong>de</strong>l comunicador comm.– Existen implementaciones bloqueantes y no bloqueantesint <strong>MPI</strong>_Recv ( void *buf, int count, <strong>MPI</strong>_Datatype datatype, int source, int tag,<strong>MPI</strong>_Comm comm, <strong>MPI</strong>_Status *status )– Recibe mensaje <strong>de</strong> proceso source <strong>de</strong>ntro <strong>de</strong>l comunicador comm.• Semántica bloqueante– Sólo se recibe un mensaje enviado <strong>de</strong>s<strong>de</strong> source con etiqueta tag pero existenargumentos comodín: <strong>MPI</strong>_ANY_SOURCE, <strong>MPI</strong>_ANY_TAG.– Mensaje es almacenado en posiciones continuas <strong>de</strong>s<strong>de</strong> buf.commsourcebufbuf<strong>de</strong>st
2. Funciones <strong>MPI</strong> básicas2.4. Envío y recepción <strong>de</strong> mensajes (cont.)– Argumentos count y datatype: especifican la longitud <strong>de</strong>l buffer.– Objeto status → Estructura con campos <strong>MPI</strong>_SOURCE y <strong>MPI</strong>_TAG.– Permite obtener información sobre el mensaje recibido– Obtener tamaño <strong>de</strong>l mensaje recibido: Función <strong>MPI</strong>_Get_count– int <strong>MPI</strong>_Get_count( <strong>MPI</strong>_Status *status, <strong>MPI</strong>_Datatype dtype, int *count )Ejemplo: Programa para dos procesos<strong>MPI</strong>_Init( &argc, &argv );<strong>MPI</strong>_Comm_rank( <strong>MPI</strong>_COMM_WORLD, &rank );<strong>MPI</strong>_Comm_size( <strong>MPI</strong>_COMM_WORLD, &size );if (rank == 0) { value=100;<strong>MPI</strong>_Send (&value, 1, <strong>MPI</strong>_INT, 1, 0, <strong>MPI</strong>_COMM_WORLD );else <strong>MPI</strong>_Recv ( &value, 1, <strong>MPI</strong>_INT, 0, 0, <strong>MPI</strong>_COMM_WORLD, &status );<strong>MPI</strong>_Finalize( );
2. Funciones <strong>MPI</strong> básicas2.4. Envío y recepción <strong>de</strong> mensajes. Ejemplo#inclu<strong>de</strong> #inclu<strong>de</strong> "mpi.h"int main(int argc, char **argv); {P0valueint rank, value, size; <strong>MPI</strong>_Status status;<strong>MPI</strong>_Init( &argc, &argv );P1 value<strong>MPI</strong>_Comm_rank( <strong>MPI</strong>_COMM_WORLD, &rank );<strong>MPI</strong>_Comm_size( <strong>MPI</strong>_COMM_WORLD, &size );P2 valuedo {P3if (rank == 0) { scanf( "%d", &value );<strong>MPI</strong>_Send( &value, 1, <strong>MPI</strong>_INT, rank + 1, 0, <strong>MPI</strong>_COMM_WORLD ); }else { <strong>MPI</strong>_Recv( &value, 1, <strong>MPI</strong>_INT, rank - 1, 0, <strong>MPI</strong>_COMM_WORLD, &status );if (rank < size - 1) <strong>MPI</strong>_Send( &value, 1, <strong>MPI</strong>_INT, rank + 1, 0, <strong>MPI</strong>_COMM_WORLD )}printf( "Process %d got %d\n", rank, value ); }while (value >= 0); <strong>MPI</strong>_Finalize( ); return 0; }
3. Envío y recepciónsimultáneaint <strong>MPI</strong>_Sendrecv( void *sendbuf, int sendcount, <strong>MPI</strong>_Datatype sendtype, int <strong>de</strong>st, intsendtag, void *recvbuf, int recvcount, <strong>MPI</strong>_Datatype recvtype, int source, intrecvtag, <strong>MPI</strong>_Comm comm, <strong>MPI</strong>_Status *status )– Envía un mensaje a <strong>de</strong>st y simultáneamente los recibe <strong>de</strong> source– Muy útil para patrones <strong>de</strong> comunicación circulares– Combina argumentos <strong>de</strong> <strong>MPI</strong>_Send y <strong>MPI</strong>_Recv.• Los buffers <strong>de</strong>ben ser disjuntos, y se permite que source=<strong>de</strong>stsourcerecvbufsendbuf<strong>de</strong>stint <strong>MPI</strong>_Sendrecv_replace( void *buf, int count, <strong>MPI</strong>_Datatype datatype, int <strong>de</strong>st, intsendtag, int source, int recvtag, <strong>MPI</strong>_Comm comm, <strong>MPI</strong>_Status *status )– Igual que <strong>MPI</strong>_Sendrecv pero con un único buffer.– Los datos recibidos reemplazan a los enviados.– Tanto send como receive tratan con datos <strong>de</strong>l mismo tipo.
4. Operaciones <strong>de</strong>comunicación colectiva• Tienen un comunicador como argumento: <strong>de</strong>fine el grupo afectado.• Participan todos los procesos <strong>de</strong>l comunicador:– <strong>La</strong> <strong>de</strong>ben llamar todos con los mismos parámetros.– <strong>MPI</strong>_Barrier: Sincroniza todos los procesos.– <strong>MPI</strong>_Broadcast: Envía un dato <strong>de</strong> un proc. al resto.– <strong>MPI</strong>_Gather: Recolecta datos <strong>de</strong> todos los procesos a uno.– <strong>MPI</strong>_Scatter: Reparte datos <strong>de</strong> un proceso a todos.– <strong>MPI</strong>_Reduce: Realiza operaciones simples sobre datos distribuidos.– <strong>MPI</strong>_Scan: Operación <strong>de</strong> reducción <strong>de</strong> prefijo.4.1. Sincronización <strong>de</strong> barrera• int <strong>MPI</strong>_Barrier ( <strong>MPI</strong>_Comm comm )– Bloquea todos los procesos <strong>de</strong> comm hasta que todos la invoquen.
4. Operaciones <strong>de</strong>comunicación colectiva4.2. Movimiento <strong>de</strong> datosTodos los procesos interactúancon un proceso distinguido (root)para difundir, recolectar orepartir datosint <strong>MPI</strong>_Bcast ( void* buffer, intcount, <strong>MPI</strong>_Datatype datatype, introot, <strong>MPI</strong>_Comm comm )• Envía datos almacenados enbuffer (count elem. <strong>de</strong> tipodatatype) en root al resto.• Datos recibidos se almacenanen buffer, count y datatype<strong>de</strong>ben coincidir en todos.
4. Operaciones <strong>de</strong>comunicación colectiva4.2. Movimiento <strong>de</strong> datos (cont.)int <strong>MPI</strong>_Gather ( void* sendbuf, int sendcount, <strong>MPI</strong>_Datatype sendtype, void*recvbuf, int recvcount, <strong>MPI</strong>_Datatype recvtype, int root, <strong>MPI</strong>_Comm comm )– Cada proceso envía datos almacenados en el array sendbuf a root.– Proc root recibe size(comm) buffers dispuestos consecutivamente enrecvbuf.– Argumentos sendtype y sencount→ mismos valores en todos los procs.– recvcount=nº items recibidos <strong>de</strong> cada proc ⇒ recvcount=sendcount, sisendtype coinci<strong>de</strong> con recvtype.– Información sobre buffer <strong>de</strong> recepción sólo tiene sentido en root.int <strong>MPI</strong>_Scatter(void* sendbuf, int sendcount, <strong>MPI</strong>_Datatype sendtype, void*recvbuf, int recvcount, <strong>MPI</strong>_Datatype recvtype, int root, <strong>MPI</strong>_Comm comm)– source envía una parte diferente <strong>de</strong> sendbuf al recvbuf <strong>de</strong> cada proc.– Todos con mismos valores <strong>de</strong> sendcount, sendtype, recvbuf, recvcount,recvtype, root y comm.– sendcount=nº items enviados por cada proc
4. Operaciones <strong>de</strong>comunicación colectiva4.3. Operaciones <strong>de</strong> Reducción Globalint <strong>MPI</strong>_Reduce (void* sendbuf, void* recvbuf, int count, <strong>MPI</strong>_Datatypedatatype, <strong>MPI</strong>_Op op, int root, <strong>MPI</strong>_Comm comm)– Combina los elementos almacenados en sendbuf <strong>de</strong> cada proc,usando operación op. Devuelve resultado en recvbuf <strong>de</strong> root.– Args sendbuf y recvbuf <strong>de</strong>ben tener count items <strong>de</strong> tipo datatype.– Todos <strong>de</strong>ben proporcionar array recvbuf– Si count>1 ⇒ la operación se aplica elemento a elemento.– Args count, datatype, op, root, comm <strong>de</strong>ben ser idénticos en todos.– Operaciones pre<strong>de</strong>finidas• <strong>MPI</strong>_MAX (máximo), <strong>MPI</strong>_MIN (mínimo), <strong>MPI</strong>_SUM (suma), <strong>MPI</strong>_PROD(producto), <strong>MPI</strong>_LAND (AND lógico), <strong>MPI</strong>_BAND (AND bit a bit), <strong>MPI</strong>_LOR (ORlógico), PI_BOR (OR bit a bit), <strong>MPI</strong>_LXOR (XOR lógico), <strong>MPI</strong>_BXOR (XOR bit abit).• Es posible <strong>de</strong>finir otras operaciones: <strong>MPI</strong>_OP_CREATE .
4.4. Ejemplos4. Operaciones <strong>de</strong>comunicación colectiva• Difun<strong>de</strong> 20 reales <strong>de</strong> proceso 0 al resto en comunicador commdouble vector[20];<strong>MPI</strong>_Bcast ( vector, 20, <strong>MPI</strong>_DOUBLE, 0, comm);• Recoge 20 reales <strong>de</strong> cada proceso en el proceso 0<strong>MPI</strong>_Comm comm= <strong>MPI</strong>_COMM_WORLD;int gsize; double invec[20], *outvec;<strong>MPI</strong>_Comm_size( comm, &gsize);outvec = (double *)malloc(gsize*20*sizeof(double));<strong>MPI</strong>_Gather (invec, 20, <strong>MPI</strong>_DOUBLE, outvec, 20, <strong>MPI</strong>_DOUBLE, 0, comm);• Inversa anterior: Reparte 20 reales <strong>de</strong>s<strong>de</strong> proc 0<strong>MPI</strong>_Scatter( outvec, 20, <strong>MPI</strong>_DOUBLE, invec, 20, <strong>MPI</strong>_DOUBLE, 0, comm);
4. Operaciones <strong>de</strong>4.4. Ejemplos. Cálculo <strong>de</strong> π#inclu<strong>de</strong> "mpi.h"#inclu<strong>de</strong> int main(int argc, char **argv) {int n, myid, numprocs, i; double mypi, pi, h, sum, x;<strong>MPI</strong>_Init (&argc,&argv);<strong>MPI</strong>_Comm_size (<strong>MPI</strong>_COMM_WORLD,&numprocs);<strong>MPI</strong>_Comm_rank (<strong>MPI</strong>_COMM_WORLD,&myid);if (myid == 0) { printf(“Number of intervals: "); scanf("%d",&n); }<strong>MPI</strong>_Bcast (&n, 1, <strong>MPI</strong>_INT, 0, <strong>MPI</strong>_COMM_WORLD);h = 1.0 / (double) n; sum = 0.0;for (i = myid + 1; i
5. Comunicación Nobloqueante• <strong>La</strong>s operaciones <strong>de</strong> comunicación vistas son “bloqueantes”– Incluso <strong>MPI</strong>_Send pue<strong>de</strong> ser bloqueante si la implementación nosoporta suficiente buferización.• Se necesitan operaciones <strong>de</strong> comunicación no bloqueantes– Solapar comunicación con computación:• <strong>MPI</strong>_Isend: Inicia envío pero retorna antes <strong>de</strong> copiar en buffer.• <strong>MPI</strong>_Irecv: Inicia recepción pero retorna antes <strong>de</strong> recibir.• <strong>MPI</strong>_Test: Chequea si la operación no bloqueante ha finalizado.• <strong>MPI</strong>_Wait: Bloquea hasta que acabe la operación no bloqueante.– Comunicación Asíncrona, .• <strong>MPI</strong>_Iprobe: Chequeo no bloqueante para un mensaje.• <strong>MPI</strong>_Probe: Chequeo bloqueante para un mensaje.
5. Comunicación No5.1. Solapando Comunicación con Computación• int <strong>MPI</strong>_Isend(void* buf, int count, <strong>MPI</strong>_Datatype datatype, int <strong>de</strong>st, inttag, <strong>MPI</strong>_Comm comm, <strong>MPI</strong>_Request *request)• int <strong>MPI</strong>_Irecv(void* buf, int count, <strong>MPI</strong>_Datatype datatype, int source, inttag, <strong>MPI</strong>_Comm comm, <strong>MPI</strong>_Request *request)– Argumento request: I<strong>de</strong>ntifica operación cuyo estado se preten<strong>de</strong>consultar o se espera que finalice.– No incluyen argumento status: Se obtiene con otras 2 funciones• int <strong>MPI</strong>_Test(<strong>MPI</strong>_Request *request, int *flag, <strong>MPI</strong>_Status *status)– flag > 0 ⇒ operación i<strong>de</strong>ntificada ha finalizado, libera request ,inicializa statusbloqueante– Versión para varias count operaciones : int <strong>MPI</strong>_Testall (int count,<strong>MPI</strong>_Request *array_of_requests, int *flag, <strong>MPI</strong>_Status*array_of_statuses)
5. Comunicación Nobloqueante5.1. Solapando Comunicación con Computación (cont.)• int <strong>MPI</strong>_Wait(<strong>MPI</strong>_Request *request, <strong>MPI</strong>_Status *status)– Bloquea hasta que operación finaliza– Versión para varias count operaciones : int <strong>MPI</strong>_Waitall( intcount, <strong>MPI</strong>_Request array_of_requests[], <strong>MPI</strong>_Statusarray_of_statuses[] )• Posible conectar operaciones no bloqueantes con contrapartesbloqueantes– int <strong>MPI</strong>_Request_free(<strong>MPI</strong>_Request *request) ⇒ Liberaciónexplícita request
5. Comunicación Nobloqueante5.2. Comunicación Asíncrona. Son<strong>de</strong>o <strong>de</strong> mensajes.• Accceso no estructurado a recurso compartido– Comprobar existencia <strong>de</strong> mensajes sin recibirlos• int <strong>MPI</strong>_Iprobe( int source, int tag, <strong>MPI</strong>_Comm comm, int *flag,<strong>MPI</strong>_Status *status )– No bloquea si no hay mensajes,. Si hay mensaje, se recibe con<strong>MPI</strong>_Recv– flag > 0 ⇒ ∃ mensaje pendiente que encaja con (source, tag, comm).• Más información mediante status.• int <strong>MPI</strong>_Probe(int source, int tag, <strong>MPI</strong>_Comm comm, <strong>MPI</strong>_Status*status )– Retorna sólo cuando hay mensaje que encaje con los argumentos.– Esperar la llegada mensaje sin conocer proce<strong>de</strong>ncia, etiqueta otamaño.
5. Comunicación Nobloqueante5.2. Comunicación Asíncrona. Ejemplo.• Recepción <strong>de</strong> fuente <strong>de</strong>sconocidaint count, *buf, source;<strong>MPI</strong>_Probe(<strong>MPI</strong>_ANY_SOURCE, 0, comm, &status);<strong>MPI</strong>_Get_count(status, <strong>MPI</strong>_INT, &count);buf=malloc(count*sizeof(int));source= status.<strong>MPI</strong>_SOURCE;<strong>MPI</strong>_Recv(buf, count, <strong>MPI</strong>_INT, source, 0, comm, &status);
6. Comunicadores• int <strong>MPI</strong>_Comm_split ( <strong>MPI</strong>_Comm comm, int color, int key,<strong>MPI</strong>_Comm *comm_out )– Operación colectiva que divi<strong>de</strong> grupo asociado a comm ensubgrupos, cada uno asociado a un comunicador diferentecomm_out.– Cada subgrupo contiene los procesos con el mismo valor <strong>de</strong>color.– color=<strong>MPI</strong>_UNDEFINED ⇒proceso no pertenece a nuevogrupo– <strong>La</strong> or<strong>de</strong>nación en el nuevo grupo se hace en base a key.• int <strong>MPI</strong>_Comm_free(<strong>MPI</strong>_Comm *comm)– Libera el comunicador comm
6. Comunicadores6.1. Ejemplos <strong>de</strong> creación <strong>de</strong> comunicadores<strong>MPI</strong>_Comm comm, comm1,comm2,comm3;int myid, color;<strong>MPI</strong>_Comm_rank(comm, &myid);color = myid%3;<strong>MPI</strong>_Comm_split (comm, color, myid, &comm1);if (myid < 8) color = 1; else color = <strong>MPI</strong>_UNDEFINED;<strong>MPI</strong>_Comm_split (comm, color, myid, &comm2);• comm2= Nuevo Comunicadorcon 8 primeros procs <strong>de</strong> comm.<strong>MPI</strong>_Comm_split (comm, 0, myid, &comm3);• comm3= Nuevo Comunicadorcon el mismo grupo <strong>de</strong> procsque comm.
6. Comunicadores6.2. Objetivos <strong>de</strong> los Comunicadores. Modularidad• Restringir <strong>de</strong>terminadas operaciones comunicación a ciertosgrupos → Implementación mo<strong>de</strong>lo MPMD– Programación por grupos• Separar paso <strong>de</strong> mensajes en grupos <strong>de</strong> procesos solapados.– Etiquetas no bastan. Fallan para <strong>de</strong>sarrollo modular.– Aplicación que usa módulo <strong>de</strong> biblioteca– Asegurar que el módulousa diferentes etiquetas– Solución: Nuevo comunicador• Argumento <strong>de</strong>l módulo• Desacopla paso <strong>de</strong> mensajes
7. Topologías Cartesianas• Numeración lineal (0,…,P-1) → No apropiada para algunas aplicaciones.– Ejemplo: Algoritmos <strong>de</strong> multiplicación <strong>de</strong> matrices → Malla 2D– Asignar proceso <strong>MPI</strong> a un proceso en una topología n-dimensional7.1. Creación• int <strong>MPI</strong>_Cart_create ( <strong>MPI</strong>_Comm comm_old, int ndims, int *dims, int*periods, int reor<strong>de</strong>r, <strong>MPI</strong>_Comm *comm_cart )– Crea comunicador cartesiano comm_cart con ndims dimensiones apartir <strong>de</strong> comm.– dims[i] = número <strong>de</strong> procesos en dimensión i-ésima.– periods[i] > 0 ⇒ dimensión i periódica, periods[i]=0 ⇒ No periódica– reor<strong>de</strong>r=0 ⇒ Se sigue la numeración <strong>de</strong> comm.– reor<strong>de</strong>r>0 ⇒ Se permite que <strong>MPI</strong> reor<strong>de</strong>ne la numeración según suconveniencia, por ejemplo, para hacer coincidir la topología con latopología física <strong>de</strong> la red.
7. Topologías Cartesianas7.2. I<strong>de</strong>ntificación <strong>de</strong> procesos.• int <strong>MPI</strong>_Cart_coords (<strong>MPI</strong>_Comm comm_cart, int rank, int maxdims, int*coords )– Devuelve coor<strong>de</strong>nadas <strong>de</strong>l proceso rank <strong>de</strong>ntro <strong>de</strong>l comunicadorcartesiano comm_cart con maxdims dimensiones– coords= array, coor<strong>de</strong>nadas <strong>de</strong>l proc. en cada dimensión.• int <strong>MPI</strong>_Cart_rank ( <strong>MPI</strong>_Comm comm_cart, int *coords, int *rank )– Devuelve el i<strong>de</strong>ntificador (rank) <strong>de</strong>l proceso que tiene lascoor<strong>de</strong>nadas coords en el comunicador cartesiano comm_cart.• int <strong>MPI</strong>_Cart_shift ( <strong>MPI</strong>_Comm comm_cart, int direction, int displ, int*source, int *<strong>de</strong>st )– Devuelve el i<strong>de</strong>ntificador <strong>de</strong> los procesos fuente y <strong>de</strong>stino (source,<strong>de</strong>st) para una operación <strong>de</strong> <strong>de</strong>splazamiento <strong>de</strong> displ pasos (displ>0 →arriba, < 0 → abajo) en la dimensión direction <strong>de</strong>ntro <strong>de</strong> comm_cart.
7. Topologías Cartesianas7.3. Ejemplo.<strong>MPI</strong>_Comm comm_2d;int myrank, size, P, Q, p, q, reor<strong>de</strong>r; <strong>MPI</strong>_Status status;int dims[2], local[2], period[2];int remain_dims[2],izqda, dcha, abajo, arriba;double buf;……………………..:::::::::::::::::::::::::::::::<strong>MPI</strong>_Comm_rank (<strong>MPI</strong>_COMM_WORLD, &myrank);dims[0] = dims[1] = 2; reor<strong>de</strong>r = 0; period[0] =1; period[1] = 0;0 12 3<strong>MPI</strong>_Cart_create(<strong>MPI</strong>_COMM_WORLD, 2, dims, period, reor<strong>de</strong>r, &comm_2d);<strong>MPI</strong>_Cart_coords(comm_2d, myrank, 2, local);<strong>MPI</strong>_Cart_shift(comm_2d, 1, 1, &arriba, &abajo);<strong>MPI</strong>_Sendrecv_replace( &buf, 1, <strong>MPI</strong>_DOUBLE, arriba, 0, abajo, 0, comm_2d, &status)
8. Tipos <strong>de</strong> datos <strong>de</strong>rivadosy empaquetado• int <strong>MPI</strong>_Type_vector( int count, int blocklen, int stri<strong>de</strong>,<strong>MPI</strong>_Datatype old_type, <strong>MPI</strong>_Datatype *newtype )– Crea tipo newtype = count bloques (cada uno con blocklenunida<strong>de</strong>s <strong>de</strong> tipo old_type) separados por stri<strong>de</strong> unida<strong>de</strong>s.• int <strong>MPI</strong>_Type_commit ( <strong>MPI</strong>_Datatype *datatype )– Prepara el nuevo tipo datatype para su uso en una función <strong>de</strong>comunicación.• int <strong>MPI</strong>_Type_free ( <strong>MPI</strong>_Datatype *datatype )– Libera el tipo <strong>de</strong> datos datatype
8. Tipos <strong>de</strong> datos <strong>de</strong>rivadosy empaquetado8.1. Ejemplo <strong>de</strong> Tipos <strong>de</strong> datos <strong>de</strong>rivados• Enviar un bloque 4x4, comenzando por A[0][2] <strong>de</strong> una matriz A <strong>de</strong>proceso 0 al 1float A[10][10];<strong>MPI</strong>_Datatype bloque;……………..<strong>MPI</strong>_Type_vector(4,4,10,<strong>MPI</strong>_FLOAT,&bloque);<strong>MPI</strong>_Type_commit(&bloque);If (myrank==0)<strong>MPI</strong>_Send(&(A[0][2]),1,bloque,1,0, <strong>MPI</strong>_COMM_WORLD);else<strong>MPI</strong>_Sendrecv(&(A[0][2]),1,bloque, 0, 0, <strong>MPI</strong>_COMM_WORLD,&status);
8. Tipos <strong>de</strong> datos <strong>de</strong>rivados8.3. Empaquetando datosy empaquetado• int <strong>MPI</strong>_Pack ( void *inbuf, int incount, <strong>MPI</strong>_Datatype datatype, void*outbuf, int outcount, int *position, <strong>MPI</strong>_Comm comm )– Empaqueta mensaje (inbuf , incount, datatype) en área contigua conoutcount bytes, <strong>de</strong>s<strong>de</strong> outbuf.– Entrada position = 1ª posición buffer salida a usar para empaquetar.– position se incrementa en el tamaño <strong>de</strong>l mensaje empaquetado– Salida <strong>de</strong> position = 1ª posición en buffer salida <strong>de</strong>spués empaquetar.– comm= comunicador para enviar mensaje empaquetado.– Mensaje empaquetado se envía como tipo <strong>MPI</strong>_PACKED• Función <strong>de</strong> Temporización (para medir tiempos)double <strong>MPI</strong>_Wtime() → Tiempo <strong>de</strong> retardo (en segs.) <strong>de</strong>s<strong>de</strong> un tiempoarbitrario en el pasado.
8. Tipos <strong>de</strong> datos <strong>de</strong>rivados8.3.1. Desempaquetando datosy empaquetado• int <strong>MPI</strong>_Unpack ( void *inbuf, int insize, int *position, void *outbuf, intoutcount, <strong>MPI</strong>_Datatype datatype, <strong>MPI</strong>_Comm comm )– Desempaqueta mensaje en (outbuf, outcount, datatype) <strong>de</strong>s<strong>de</strong> el áreacontigua con insize bytes que comienza en inbuf.– Entrada position= 1ª posición en buffer <strong>de</strong> entrada ocupada por elmensaje empaquetado.– position se incrementa en el tamaño <strong>de</strong>l mensaje empaquetado– Salida <strong>de</strong> position= 1ª posición en buffer entrada <strong>de</strong>spués <strong>de</strong>empaquetar posiciones ocupadas por el mensaje <strong>de</strong>sempaquetado.– comm=comunicador para recibir mensaje empaquetado
8. Tipos <strong>de</strong> datos <strong>de</strong>rivadosy empaquetado8.3.2. Empaquetando datos. Ejemploint position, i, j, a[2]; char buff[1000]; <strong>MPI</strong>_Comm comm= <strong>MPI</strong>_COMM_WORLD;....<strong>MPI</strong>_Comm_rank(<strong>MPI</strong>_COMM_WORLD, &myrank);if (myrank == 0){ position = 0;<strong>MPI</strong>_Pack(&i, 1, <strong>MPI</strong>_INT, buff, 1000, &position, comm);<strong>MPI</strong>_Pack(&j, 1, <strong>MPI</strong>_INT, buff, 1000, &position , comm);<strong>MPI</strong>_Send( buff, position, <strong>MPI</strong>_PACKED, 1, 0 , comm); }else<strong>MPI</strong>_Recv( a, 2, <strong>MPI</strong>_INT, 0, 0 , comm);/* ALTERNATIVA A LO ANTERIOR */{ <strong>MPI</strong>_Recv( buff, 1000, <strong>MPI</strong>_PACKED, 0, 0, &status);position = 0; <strong>MPI</strong>_Unpack(buff, 1000, &position, &i, 1, <strong>MPI</strong>_INT, comm);<strong>MPI</strong>_Unpack(buff, 1000, &position, &j, 1, <strong>MPI</strong>_INT, comm) }
9. Referencias útilesReferencias bibliográficas• <strong>MPI</strong>: A Message-Passing Interface Standard– http://www-unix.mcs.anl.gov/mpi/mpi-standard/mpi-report-1.1/mpi-report.html• <strong>MPI</strong>: The complete reference– Marc Snir, Steve Otto, Steven Huss-Le<strong>de</strong>rman, David Walker and JackDongara, MIT Press– /nfs/workshops/mpi/docs/mpi_complete_reference.ps.Z• Parallel Programming with <strong>MPI</strong>– Peter S. Pacheco, Morgan Kaufman Publishers, Inc• Using <strong>MPI</strong>: Portable Parallel Programing with Message PassingInterface– William Gropp, E. Lusk and A. Skjellum, MIT Press