1 / 153

. 3 . P ROGRAMACIÓN DE S ISTEMAS DE M EMORIA D ISTRIBUIDA : MPI

. 3 . P ROGRAMACIÓN DE S ISTEMAS DE M EMORIA D ISTRIBUIDA : MPI. Índice. 1. Introducción. 2. Funciones MPI básicas. 3. Otros modos de envío y recepción. 4. Comunicación en grupo. 5. Tipos de datos derivados. 6. Comunicadores y topologías. 7. Entrada/salida paralela (introd.).

lamar
Download Presentation

. 3 . P ROGRAMACIÓN DE S ISTEMAS DE M EMORIA D ISTRIBUIDA : MPI

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. . 3 . • PROGRAMACIÓNDESISTEMAS DE MEMORIA DISTRIBUIDA: • MPI

  2. Índice • 1. Introducción. • 2. Funciones MPI básicas. • 3. Otros modos de envío y recepción. • 4. Comunicación en grupo. • 5. Tipos de datos derivados. • 6. Comunicadores y topologías. • 7. Entrada/salida paralela (introd.). • 8. Performance, debugging, profiling...

  3. Introducción Paralelizar una aplicación para que se ejecute en un sistema de memoria compartida SMP “no es muy complejo”. El uso de variables compartidas facilita la comunicación entre procesos, aunque implica: – analizar detalladamente el tipo de variables. – sincronizar correctamente el acceso a las variables compartidas. Sin embargo, el número de procesadores de un sistema SMP no suele ser muy grande, por lo que no es fácil conseguir altos niveles de paralelismo.

  4. Introducción  Es relativamente sencillo conseguir una máquina paralela tipo cluster con muchos procesadores, uniendo P máquinas independientes mediante una red de conexión estándar.  Por ejemplo, nosotros vamos a utilizar una máquina de 32 + 3 nodos (32 + 3x4 = 44 pr.), unidos mediante una red gigabit ethernet. No es una máquina de alto rendimiento, pero es “barata” y sencilla de ampliar (en nodos de cálculo y en comunicación).

  5. Introducción  Sin embargo, programar aplicaciones para sistemas de memoria distribuida es más complejo. •  Recuerda: • • la memoria de cada procesador es de uso privado, por lo que todas las variables son, por definición, privadas. • •la comunicación entre procesos debe hacerse a través de paso explícito de mensajes. • • la red de comunicaciónjuega un papel importante en el rendimiento del sistema.

  6. Introducción  Diferentes alternativas para programar aplicaciones: •utilizar lenguajes diseñados específicamente para sistemas paralelos (OCCAM). • ampliar la sintaxis de un lenguaje estándar para gestionar el paso de mensajes (Fortran M). • utilizar un lenguaje estándary unalibrería de funciones de comunicación.

  7. Introducción  Necesitamos: - un método para crear procesos: estático /dinámico. - un método paraenviar y recibir mensajes, punto a punto y de manera global. El estándar actual de programación de los sistemas de memoria distribuida, mediante paso de mensajes, es MPI (message-passing interface). PVM → MPI 1.0 (94) → MPI 2.0 (97)

  8. Introducción MPI es, básicamente, una librería (grande) de funciones de comunicación para el envío y recepción de mensajes entre procesos. Para Fortran y C. Se busca: portabilidad, eficiencia... El objetivo de MPI es explicitar la comunicación entre procesos, es decir: > el movimiento de datosentre procesadores > la sincronización de procesos

  9. Introducción El modelo de paralelismo que implementa MPI es SPMD(Single Program Multiple Data). if (pid==1) ENVIAR_a_pid2 else if (pid==2)RECIBIR_de_pid1 Recuerda que cada proceso dispone de su propio espacio de direcciones. También se puede trabajar con un modelo MPMD (Multiple Program Multiple Data): se ejecutan programas diferentes en los nodos.

  10. Introducción MPI gestiona los procesos (número y asignación) de manera estática (MPI2 permite gestión dinámica de procesos). La comunicación entre procesos puede hacerse de formas muy diferentes. Elegiremos una determinada estrategia en función de la longitud de los mensajes, de la estructura del programa...

  11. Introducción En todo caso, ten en cuenta que la eficiencia en la comunicación va a ser determinante en el rendimiento del sistema paralelo, sobre todo en aquellas aplicaciones en las que la comunicación juega un papel importante (paralelismo de grano medio / fino). Además de implementaciones específicas, dos imple-mentaciones libres de uso muy extendido: LAM y MPICH. Nosotros vamos a usar MPICH.

  12. nodo00 nodoxx g000002.gi.ehu.es gigabit ethernet check datos tipo @orig @dest cabecera 4 bytes < 1,5 Kbytes 2 bytes 6 bytes 6 bytes 8 bytes Introducción: el cluster • Recuerda: ethernet • - switch / conmutación de paquetes • - formato de paquetes • - direcciones IP: 32 bits (4 × 8) • - direcciones del NIC (MAC, 48 bits)

  13. Introducción: el cluster Para poder ejecutar MPI en el cluster: • 1.Generar fichero de claves para ssh • >ssh-keygen –t rsa • (pasar al directorio .ssh) • > cp id_rsa.pub authorized_keys • > chmod go-rw authorized_keys • (salir del directorio .ssh) • Entrar la primera vez en cada máquina: • > ssh nodo01 ..... yes .... exit • 2.Crear en el directorio principal el fichero .mpd.conf con una línea que ponga:secretword=xxxxx • > chmod 600 .mpd.conf

  14. Introducción: el cluster El proceso de compilación/ejecución de programas MPI depende de la implementación concreta. En el caso de MPICH2: • 1. Lanzar daemons en cada procesador: • >mpdboot –v –n zz –f fichero_maquinas • 2.Tras compilar (mpicc …), ejecutar el programa (spmd): • > mpiexec –n xx programa • 2’. En su caso (mpmd), indicar qué ejecutar en cada nodo: • > mpiexec –n1–host nodo00p1:-n1–host nodo01p2 • (o en un fichero)

  15. Introducción: el cluster Algunas herramientas para gestionar el cluster como si fuera una máquina única. Una muy sencilla es C3(Cluster Command and Control suite). http://www.csm.ornl.gov/torc/C3 Fichero de configuración cluster cluster32 { g000002:nodo00 #head node dead 0 nodo0[1-9] nodo[10-31] acpt48 acpt49 acpt51 } Algunos comandos cshutdown clist, cname, cnum cget, cpush, cpushimage crm ckill, cexec

  16. Índice 1. Introducción. 2. Funciones MPI básicas inicio y control de procesos envío y recepción de mensajes 3. Otros modos de envío y recepción. 4. Comunicación en grupo. 5. Tipos de datos derivados. 6. Comunicadores y topologías. 7. Entrada/salida paralela (introd.). 8. Performance, debugging, profiling...

  17. Funciones básicas Aunque MPI consta de más de 320 funciones, el núcleo básico lo forman sólo 6: 2 de inicio y finalización del programa. 2 de control del número de procesos. 2 de comunicación. Sintaxis: MPI_Funcion(…) #include <mpi.h>

  18. Funciones básicas •  Los parámetros de las funciones MPI son de tres tipos: • IN: la función lee el argumento • OUT: la función modifica el argumento • IN/OUT: la funciónlee y modifica el argumento Las funciones MPI (casi todas) devuelven un entero como código de error. error = MPI_Funcion(...) Si no ha habido problemas, MPI_SUCCESS (0 en esta implementación); en caso de errores, el valor que indica el tipo de error depende de la implementación.

  19. F. básicas: Init / Finalize 1.Comienzo y final del programa: > MPI_Init(&argc,&argv); > MPI_Finalize(); Estas dos funciones son la primera y última función MPI que deben ejecutarse en un programa. No se pueden utilizar funciones MPI antes de _Init, y si un proceso no ejecuta _Finalize el programa queda como “colgado”.

  20. Funciones básicas Los procesos que se van a ejecutar se agrupan en conjuntos denominados comunicadores. Cada proceso tiene un identificador o pid en cada comunicador. El comunicadorMPI_COMM_WORLD (un objeto de tipo MPI_COMM) se crea por defecto y engloba a todos los procesos.

  21. F. básicas: Comm_rank / _size 2.Identificación de procesos • > MPI_Comm_rank(comm,&pid); • Devuelve en pid (int) el identificador del proceso dentro del grupo de procesos, comunicadorcomm, especificado. • Recuerda que un proceso se identifica mediante dos parámetros: identificador (pid) y grupo (comm). • > MPI_Comm_size(comm,&npr); • Devuelve en npr (int) el número de procesos del comunicador especificado.

  22. Funciones básicas Un ejemplo simple #include <stdio.h> #include <mpi.h> main (int argc, char *argv[]) { int pid, npr, A = 2; MPI_Init(&argc, &argv); MPI_Comm_rank(MPI_COMM_WORLD, &pid); MPI_Comm_size(MPI_COMM_WORLD, &npr); A = A + 1; printf(“Proceso %d de %d activado. A = %d \n”, pid, npr, A); MPI_Finalize(); }

  23. Funciones básicas Otro ejemplo: planificación de un bucle ... main (int argc, char *argv[]) { ... MPI_Init(&argc, &argv); MPI_Comm_rank(MPI_COMM_WORLD, &pid); MPI_Comm_size(MPI_COMM_WORLD, &npr); for (i=pid; i<N; i=i+npr) func(i); MPI_Finalize(); }

  24. F. básicas: comunicación 3.Envío y recepción de mensajes MPI ofrece dos (tres) tipos de comunicación: punto a punto, del proceso i al j (participan ambos). en grupo (colectiva): entre un grupo de procesos, de uno a todos, de todos a uno, o de todos a todos. one-sided: del proceso i al j (participa uno solo). Además, básicamente en el caso de comunicación entre dos procesos, hay múltiples variantes en función de cómo se implementa el proceso de envío y de espera.

  25. A B enviar recibir F. básicas: comunicación 3.Envío y recepción de mensajes entre dos procesos La comunicación entre procesos requiere (al menos) de dos participantes: emisor y receptor. El emisor ejecuta una función de envío y el receptor otra de recepción. La comunicación es un proceso cooperativo: si una de las dos funciones no se ejecuta, no se produce la comunicación (y podría generarse un deadlock).

  26. EMI REC RTS RTR D F. básicas: comunicación MPI ofrece diferentes modo de comunicación. Veamos un resumen. Modos de comunicación (1) • síncrona: la comunicación no se produce hasta que emisor y receptor se ponen de acuerdo (sin búfer intermedio). - petición de transmisión (espera) - aceptación de transmisión - envío de datos (de usuario a usuario)

  27. REC EMI usuario s.o. usuario s.o. F. básicas: comunicación Modos de comunicación (1) • con búfer (buffered):el emisor deja el mensaje en un búfer y retorna. La comunicación se produce cuando el receptor está dispuesto a ello. El búfer no se puede reutilizar hasta que se vacíe. ¡Ojo con el tamaño del búfer!

  28. F. básicas: comunicación Modos de comunicación (2) •bloqueante Se espera a que la “comunicación” se produzca, antes de continuar con la ejecución del programa. La comunicación síncrona es bloqueante. La comunica- ción con búfer también, si el mensaje no cabe en el búfer. • no bloqueante Se retorna “inmediatamente” de la función de comunica- ción, y se continúa con la ejecución. Se comprueba más tarde si la comunicación se ha efectuado.

  29. F. básicas: comunicación Cada estrategia tiene sus ventajas e inconvenien-tes: > síncrona: es más rápida si el receptor está dispuesto a recibir; nos ahorramos la copia en el búfer. Además del intercambio de datos, sirve para sincronizar los procesos. Ojo: al ser bloqueante es posible un deadlock! > con búfer: elemisor no se bloqueasi el receptor no está disponible, pero hay que hacer copia(s) del mensaje (más lento).

  30. F. básicas: comunicación Para enviar o recibir un mensaje es necesario especificar: •a quién se envía (o de quién se recibe) • los datos a enviar (dirección de comienzo y cantidad) • el tipo de los datos • la clase de mensaje (tag) Todo lo que no son los datos forma el “sobre” del mensaje (que se puede “procesar”). Las dos funciones estándar para enviar y recibir mensajes son:

  31. F. básicas: Send y Recv Función estándar para enviar un mensaje: > MPI_Send(&mess,count,type,dest, tag,comm); - mensaje a enviar: [mess(@comienzo), count(tamaño), type] - receptor: [dest(@destino), comm(comunicador)] - tag: 0..32767(clase de mensajes, orden...) Tipos : MPI_CHAR, INT, LONG, FLOAT, DOUBLE,BYTE... Sendutiliza la capacidad de buffering del sistema; es decir, retorna una vez copiado en el búfer el mensaje a enviar… ¡siempre que quepa!

  32. F. básicas: Send y Recv Función básica para recibir un mensaje: > MPI_Recv(&mess,count,type,source, tag,comm,&status); - mensaje a recibir: [mess, count, type] - emisor: [source, comm] - tag: clase de mensaje - status:devuelve información sobre el mensaje recibido Recvse bloquea hasta que se efectúa la recepción.

  33. F. básicas: Send y Recv • Algunas precisiones: •source, dest, count y tag son enteros (int); comm y status son de tipo MPI_CommyMPI_Status. • para que la comunicación se efectúe tienen que coincidir las direcciones de emisor y receptor, y el tag del mensaje. • el tamaño del mensaje (count) definido en la función Recv debe ser igual o mayor al definido en Send. • el origen de un mensaje en la función Recv puede ser MPI_ANY_SOURCE, y el tipo de mensaje puede ser MPI_ANY_TAG.

  34. F. básicas: Send y Recv Algunas precisiones: • •status es un struct con tres campos, en el que se devuelve información sobre el mensaje recibido: • status.MPI_SOURCE: indica el emisor del mensaje • status.MPI_TAG: devuelve el tag del mensaje recibido • status.MPI_ERROR: devuelve un código de error • (aunque lo más habitual es abortar en caso de error) • también puede obtenerse el tamaño del mensaje recibido ejecutando: > MPI_Get_count(&status,type,&count);

  35. F. básicas: Send y Recv Algunas precisiones: • •si un proceso tiene varios mensajes pendientes de recibir, no se reciben en el orden en que se enviaron sino en el que se indica en la recepción mediante los parámetros de origen y tag del mensaje. • •si el tag del mensaje que se recibe puede ser cualquiera, los mensajes que provienen del mismo origen se reciben en el orden en que se enviaron.

  36. Ejemplo ... #define N 10 int main (int argc, char **argv) { int pid, npr, orig, dest, ndat, tag; inti, VA[N]; MPI_Status info; MPI_Init(&argc, &argv); MPI_Comm_rank(MPI_COMM_WORLD,&pid); for (i=0;i<N;i++) VA[i] = 0; if (pid== 0) { for (i=0;i<N;i++) VA[i] = i; dest = 1; tag = 0; MPI_Send(&VA[0],N,MPI_INT,dest,tag, MPI_COMM_WORLD); } else if (pid== 1) { for (i=0;i<N;i++)printf(“%4d”,VA[i]); orig = 0; tag = 0; MPI_Recv(&VA[0], N, MPI_INT, orig, tag, MPI_COMM_WORLD, &info); MPI_Get_count(&info,MPI_INT,&ndat); printf(“Datos desde pr %d; tag = %d, ndat = %d \n”, info.MPI_SOURCE, info.MPI_TAG, ndat); for(i=0;i<ndat;i++) printf(“%4d”,VA[i]); } MPI_Finalize(); }

  37. F. básicas: Probe ¿Y si se desconoce el tamaño del mensaje que hay que recibir (p.e., se calcula dinámicamente)? •Lo más sencillo, mandar primero un mensaje con la longitud del segundo mensaje. Tras ello, puede asignarse la memoria correspondiente para el mensaje que se va a recibir. •MPI_Probe(source,tag,comm,&status) permite obtener información (fuente, tamaño y tag) de un mensaje que esté a la espera de ser recibido. Podemos así reservar espacio en memoria, decidir cómo recibir el mensaje en función de quién lo envía, o incluso no recibirlo si nos basta con el tag (p.e., es un mensaje vacío, un aviso).

  38. F. básicas: temporización • Un par de funciones MPI para obtener tiempos de ejecución: • double MPI_Wtime(); • tiempo (s) transcurrido desde algún instante anterior • double MPI_Wtick(); • devuelve la precisión de la medida de tiempo t1 = MPI_Wtime(); ... t2 = MPI_Wtime(); printf(“T = %f\n”, t2-t1);

  39. F. básicas: entrada/salida Una cuestión previa sobre las operaciones de entrada/salida. Lo habitual es que sólo un proceso tenga acceso a teclado y pantalla; ese proceso se encargará de leer los datos y distribuirlos, así como de recoger resultados e imprimirlos. Un procedimiento simple para hacerlo podría ser: if (pid==0) { leer_datos(); distribuir_datos(); } else recibir_datos();

  40. Índice 1. Introducción. 2. Funciones MPI básicas. 3. Otros modos de envío/recepción comunicación síncrona, inmediata... 4. Comunicación en grupo. 5. Tipos de datos derivados. 6. Comunicadores y topologías. 7. Entrada/salida paralela (introd.). 8. Performance, debugging, profiling...

  41. Otros modos de comunicación • Aparte de las funciones estándar de envío y recepción, MPI ofrece varias alternativas con el objetivo de lograr el máximo rendimiento. • Aunque bastaría con un solo modo, cada alternativa está pensada para determinado tipo de situación. Las principales alternativas al modo estándar son: - comunicación síncrona - comunicación inmediata

  42. Comunicación síncrona • 1. Comunicación síncrona • En modo síncrono, la función de envío no retorna hasta que se produce la comunicación. • En principio, no se necesita un búfer intermedio. • >MPI_Ssend (mismos parámetros que Send); La función síncrona es bloqueante; si no se produce el correspondiente matching, habrá un deadlock.

  43. Comunicación síncrona Deadlock P1P2 Ssend_to_2; Ssend_to_1; Recv_from_2; Recv_from_1; Obviamente, hay que cambiar el orden. ¿Y con el Send estándar? P1P2 Send_to_2; Send_to_1; Recv_from_2; Recv_from_1;

  44. Comunicación síncrona • 2. Comunicación inmediata • La función de comunicación retorna sin esperar a que se produzca una determinada acción (es una especie de post/signal). • Es, por definición, no bloqueante y se busca solapar las latencias de cálculo y comunicación. La comunicación se divide en dos fases: unaviso de envío/recepción, y una verificación de que se ha producido. Se utiliza un handlepara obtener información sobre el estado de la comunicación.

  45. Comunicación inmediata • Funciones de envío y recepción • > MPI_Isend(..., &request); • > MPI_Irecv(..., &request); • request debe ser una variable de tipoMPI_Request, y se utiliza para preguntar sobre el estado de la función. • El búfer no se puede acceder hasta que la comunicación se produce. Funciones de test (status debe ser de tipo MPI_Status) > MPI_Test(&request,&flag,&status); devuelve en flag un 0 si la operación no se ha completado > MPI_Wait(&request,&status); espera hasta que la comunicación se haya efectuado

  46. Comunicación inmediata •  Ejemplo int flag = 0; // sólo parte del código MPI_Status status; int bufer[grande]; MPI_Request info; ... MPI_Isend(bufer,grande,MPI_INT,dest,tag,MPI_COMM_WORLD,&info); while(!flag && hay_tareas) { .../* realizar una tarea */ MPI_Test(&info,&flag,&status); } if (!flag)MPI_Wait(&info,&status); ...

  47. Otros modos de comunicación • Hay más opciones (muchas): - MPI_Sendrecv(…); Por ejemplo, en una comunicación en anillo, recibe del anterior y envía al siguiente, asegurando que no se produce deadlock. - Comunicación con buffering Obligamos a que la comunicación se haga mediante un búfer definido por el usuario. Hay un conjunto de funciones con esas características (Bsend, …), más otras funciones para gestionar los búferes.

  48. Otros modos de comunicación Hay más opciones (muchas): • - Comunicación persistente • Si se van a enviar repetidamente mensajes con los mismos argumentos (por ejemplo, dentro de un bucle), dividimos la comunicación en dos partes: (1)crear el contexto, una sola vez, y(2) enviar el mensaje(las veces que haga falta). > MPI_Send_init(…,&request); > MPI_Recv_init(…,&request); > MPI_Start(&request); (Isend = Send_init + Start) - Mezclas de todas ellas

  49. Resumen • La comunicación es uno de los puntos clave en el rendimiento de un sistema paralelo de memoria distribuida. Por ello, MPI ofrece una gran variedad de estrategias de comunicación. Resumen de modos de envío / recepción Modo Fun. bloq. Func. no bloq. estándar MPI_SendMPI_Isend síncrono MPI_Ssend MPI_Issend buffered MPI_Bsend MPI_Ibsend (ready MPI_Rsend MPI_Irsend) En todos los casos: Recv / Probe Irecv / Iprobe

  50. Resumen El uso recomendado sería el siguiente: MPI_Ssend:cuando es posible, ofrece los mejores resultados, puesto que no se utilizan búferes intermedios (ojo con los deadlocks). MPI_Send:la alternativa más habitual. MPI_Isend:si, por cuestiones de rendimiento, se necesitan rutinas no bloqueantes. (p.e., en clusters en los que la comunicación sea “cara”, para solapar cálculo y comunicación). El resto de opciones, para casos especiales.

More Related