Descarga la aplicación para disfrutar aún más
Vista previa del material en texto
Sistemas Paralelos Clase 5 Facultad de Informática UNLP 21-04-2015 2 Principios del paradigma de Pasaje de Mensajes Requiere hardware poco costoso. Consiste de p procesos (eventualmente procesadores) cada uno de ellos con su espacio de direcciones exclusivo. Características claves: • Espacio de direcciones particionado. ─Cada elemento pertenece a una partición. ─ Toda interacción requiere la cooperación de dos procesos. • Solo soporta paralelismo explícito. El intercambio de mensajes sirve para varios propósitos: • Intercambio explícito de Datos (programador). • Sincronizar procesos. Clase 5 21-04-2015 3 Principios del paradigma de Pasaje de Mensajes Programabilidad En pasaje de mensajes, se trabaja en bajo nivel. El programador es responsable de la distribución de datos y el scheduling de procesos, así como la comunicación entre tareas difícil de programar, difícil debugging, difícil mantenimiento. Eficiencia El ajuste (tuning) para mejorar el rendimiento puede ser óptimo. Puede manejar el balance de carga, la redistribución de datos y procesos (dinámicamente), replicar datos. Portabilidad Existen numerosas bibliotecas para facilitar la ejecución de código sobre diferentes arquitecturas (estandares) buena portabilidad de código, no necesariamente portabilidad de perfomance. Clase 5 21-04-2015 4 Estructura de los programas con Pasaje de Mensajes Los programas con Pasaje de Mensajes a menudo se escriben utilizando los paradigmas asincrónico o débilmente sincrónico. • En el paradigma asincrónico, todos los procesos ejecutan asincrónicamente. • En el modelo débilmente sincrónico, algún subconjunto de los procesos deben sincronizar para interactuar. En los tiempos entre interacciones, ejecutan en forma asincrónica. • Los procesos no están sincronizados en la ejecución de cada sentencia. • No todos realizan las mismas sentencias (sentencias de selección). Clase 5 21-04-2015 5 Principios del paradigma de Pasaje de Mensajes Ventajas: • El programador tiene total control para lograr sistemas más eficientes y escalables. • Puede implementarse eficientemente en muchas arquitecturas paralelas. • Más fácil de predecir el rendimiento. Desventajas: • Mayor complejidad al implementar estos algoritmos para lograr una buena performance. Clase 5 21-04-2015 6 Operaciones Send y Receive Los prototipos de las operaciones son: Send (void *sendbuf, int nelems, int dest) Receive (void *recvbuf, int nelems, int source) Ejemplo: P0 P1 a = 100; receive(&a, 1, 0) send(&a, 1, 1); printf("%d\n", a); a = 0; La semántica del SEND requiere que en P1 quede el valor 100 (no 0). Diferentes protocolos para Send y Receive. Clase 5 21-04-2015 7 Send y Receive bloqueante Para asegurar la semántica del SEND → no devolver el control del Send hasta que el dato a trasmitir esté seguro (Send bloqueante). Ociosidad del proceso. Hay dos posibilidades: • Send/Receive bloqueantes sin buffering. • Send/Receive bloqueantes con buffering. Clase 5 21-04-2015 8 Send y Receive bloqueante sin buffering El send se bloquea hasta que receptor no termine el receive del mensaje. Tiempo ocioso de los procesadores. Deadlocks si las sentencias de comunicación no hacen matching. P0 send(&a,1,1); receive(&b,1,1); P1 send(&a,1,0); receive(&b,1,0); Clase 5 21-04-2015 9 Send y Receive bloqueante con buffering El send se bloquea hasta que el mensaje llega a un buffer prealocado. Transmisión del mensaje: • Hardware para comunicación asincrónica (sin intervención de la CPU) → se comienza la transmisión al buffer del receptor. • Sin hardware especial → el enviador trasmite el mensaje al buffer del receptor y recién ahí se desbloquea. Clase 5 21-04-2015 10 Send y Receive bloqueante con buffering Reduce el tiempo ocioso de los procesadores y aumenta el costo por manejo de buffers. Tamaño limitado de los buffers → bloquea al send hasta que haya lugar. P0 P1 for (i=0; i<1000; i++){ for (i=0; i<1000; i++){ produce_data(&a); receive(&a, 1, 0); send(&a, 1, 1); consume_data(&a); } } Deadlocks por receive bloqueante. P0 P1 receive(&a, 1, 1) receive(&a, 1, 0) send(&b, 1, 1) send(&b, 1, 0); Clase 5 21-04-2015 11 Send y Receive no bloqueante Para evitar overhead (ociosidad o manejo de buffer) se devuelve el control de la operación inmediatamente. Requiere un posterior chequeo para asegurarse la finalización de la comunicación. Deja en manos del programador asegurar la semántica del SEND. Hay dos posibilidades: • Sin buffering: inicia comunicación al llegar al receive. • Con buffering: el enviador utiliza acceso directo a memoria (DMA) para copiar los datos a un buffer prealocado mientras el proceso continúa su computo. (Reduce el tiempo en que el dato no está seguro). Clase 5 21-04-2015 12 Send y Receive no bloqueante (cont.) Clase 5 21-04-2015 13 Resumen de los protocolos para Send y Receive Clase 5 MPI 21-04-2015 15 Librería MPI (Interfaz de Pasaje de Mensajes) Existen numerosas librerías para pasaje de mensaje (no compatibles). MPI define una librería estándar que puede ser empleada desde C o Fortran (y potencialmente desde otros lenguajes). El estándar MPI define la sintaxis y la semántica de más de 125 rutinas. Hay implementaciones de MPI de la mayoría de los proveedores de hardware. Modelo SPMD. Todas las rutinas, tipos de datos y constantes en MPI tienen el prefijo “MPI_”. El código de retorno para operaciones terminadas exitosamente es MPI_SUCCESS. Básicamente con 6 rutinas podemos escribir programas paralelos basados en pasaje de mensajes: MPI_Init, MPI_Finalize, MPI_Comm_size, MPI_Comm_rank, MPI_Send y MPI_Recv. Clase 5 21-04-2015 16 Librería MPI - Inicio y finalización de MPI MPI_Init: se invoca en todos los procesos antes que cualquier otro llamado a rutinas MPI. Sirve para inicializar el entorno MPI. MPI_Init (int *argc, char **argv) Algunas implementaciones de MPI requieren argc y argv para inicializar el entorno MPI_Finalize: se invoca en todos los procesos como último llamado a rutinas MPI. Sirve para cerrar el entorno MPI. MPI_Finalize () Clase 5 21-04-2015 17 Librería MPI - Comunicadores Un comunicador define el dominio de comunicación. Cada proceso puede pertenecer a muchos comunicadores. Existe un comunicador que incluye a todos los procesos de la aplicación MPI_COMM_WORLD. Son variables del tipo MPI_Comm → almacena información sobre que procesos pertenecen a él. En cada operación de transferencia se debe indicar el comunicador sobre el que se va a realizar. Clase 5 21-04-2015 18 Librería MPI - Adquisición de Información MPI_Comm_size: indica la cantidad de procesos en el comunicador. MPI_Comm_size (MPI_Comm comunicador, int *cantidad). MPI_Comm_rank: indica el “rank” (identificador) del proceso dentro de ese comunicador. MPI_Comm_rank (MPI_Comm comunicador, int *rank) • rank es un valor entre [0..cantidad] • Cada proceso puede tener un rank diferente en cada comunicador. EJEMPLO: #include <mpi.h> main(int argc, char *argv[]) { int cantidad, identificador; MPI_Init(&argc, &argv); MPI_Comm_size (MPI_COMM_WORLD, &cantidad); MPI_Comm_rank(MPI_COMM_WORLD, &identificador); printf(“Soy %d de %d \n", identificador, cantidad); MPI_Finalize(); } Clase 5 21-04-2015 19 Librería MPI - Tipos de Datos para las comunicaciones Tipo de Datos MPI Tipo de Datos C MPI_CHAR signed char MPI_SHORT signed short int MPI_INT signed int MPI_LONG signed long int MPI_UNSIGNED_CHAR unsignedchar MPI_UNSIGNED_SHORT unsigned short int MPI_UNSIGNED unsigned int MPI_UNSIGNED_LONG unsigned long int MPI_FLOAT float MPI_DOUBLE double MPI_LONG_DOUBLE long double MPI_BYTE MPI_PACKED Clase 5 21-04-2015 20 Librería MPI - Comunicación bloqueante punto a punto MPI_Send: rutina básica para enviar datos a otro proceso. MPI_Send (void *buf, int cantidad, MPI_Datatype tipoDato, int destino, int tag, MPI_Comm comunicador) • Valor de Tag entre [0..MPI_TAG_UB]. MPI_Recv: rutina básica para recibir datos a otro proceso. MPI_Recv (void *buf, int cantidad, MPI_Datatype tipoDato, int origen, int tag, MPI_Comm comunicador, MPI_Status *estado) • Comodines MPI_ANY_SOURCE y MPI_ANY_TAG._ • Estructura MPI_Status typedef struct MPI_Status { int MPI_SOURCE; int MPI_TAG; int MPI_ERROR; } • MPI_Get_count para obtener la cantidad de elementos recibidos MPI_Get_count(MPI_Status *estado, MPI_Datatype tipoDato, int *cantidad) MPI_Send puede ser: • MPI_Send MPI_Rsend MPI_Ssend MPI_Bsend Clase 5 21-04-2015 21 Librería MPI - Deadlock en comunicaciones punto a punto int a[10], b[10], cantProc, id; MPI_Status estado; MPI_Comm_size(MPI_COMM_WORLD, &cantProc); MPI_Comm_rank(MPI_COMM_WORLD, &id); MPI_Ssend(a, 10, MPI_INT, (id+1)%cantProc, 1,MPI_COMM_WORLD); MPI_Recv(b, 10, MPI_INT, (id-1+cantProc)%cantProc,1,MPI_COMM_WORLD, estado); Ejemplo 2 int a[10], b[10], identificador; MPI_Status estado; MPI_Comm_rank(MPI_COMM_WORLD, &identificador); if (identificador == 0) { MPI_Ssend(a, 10, MPI_INT, 1, 1, MPI_COMM_WORLD); MPI_Ssend(b, 10, MPI_INT, 1, 2, MPI_COMM_WORLD); } Else { MPI_Recv(b, 10, MPI_INT, 0, 2, MPI_COMM_WORLD, estado); MPI_Recv(a, 10, MPI_INT, 0, 1, MPI_COMM_WORLD, estado); } Ejemplo 1 ¿Que sucede con MPI_Send? Clase 5 21-04-2015 22 Librería MPI - Deadlock en comunicaciones punto a punto (cont.) int a[10], b[10], cantProc, id; MPI_Status estado; MPI_Comm_size(MPI_COMM_WORLD, &cantProc); MPI_Comm_rank(MPI_COMM_WORLD, &id); if (id%2 == 1) { MPI_Ssend(a, 10, MPI_INT, (id+1)%cantProc, 1, MPI_COMM_WORLD); MPI_Recv(b,10,MPI_INT,(id-1+cantProc)%cantProc,1,MPI_COMM_WORLD,estado); } else { MPI_Recv(b,10,MPI_INT,(id-1+cantProc)%cantProc,1,MPI_COMM_WORLD,estado); MPI_Ssend(a, 10, MPI_INT, (id+1)%cantProc, 1, MPI_COMM_WORLD); } Código para evitar el deadlock del segundo ejemplo ¿Que sucede con MPI_Send? ¿Cual código sería mejor en ese caso? Clase 5 21-04-2015 23 Librería MPI - Envío y recepción punto a punto simultánea MPI_Sendrecv: permite enviar un mensaje a un proceso y recibir otro mensaje del mismo u otro proceso. MPI_Sendrecv (void *bufEnvio, int cantEnvio, MPI_Datatype tipoDatoEnvio, int destino, int tagEnvio, void *bufRecepcion, int cantRecepcion, MPI_Datatype tipoDatoRecepcion, int origen, int tagRecepcion, MPI_Comm comunicador, MPI_Status *estado) MPI_Sendrecv_replace: igual al anterior pero utiliza un solo buffer. MPI_Sendrecv_replace (void *buf, int cant, MPI_Datatype tipoDato, int destino, int tagEnvio, int origen, int tagRecepcion, MPI_Comm comunicador, MPI_Status *estado) ¿Cuando usar cada uno ? Clase 5 21-04-2015 24 Librería MPI - Comunicación no bloqueante punto a punto Comienzan la operación de comunicación e inmediatamente devuelven el control (no se asegura que la comunicación finalice correctamente). MPI_Isend (void *buf, int cantidad, MPI_Datatype tipoDato, int destino, int tag, MPI_Comm comunicador, MPI_Request *solicitud) MPI_Irecv (void *buf, int cantidad, MPI_Datatype tipoDato, int origen, int tag, MPI_Comm comunicador, MPI_Request *solicitud) MPI_Test: testea si la operación de comunicación finalizó. MPI_Test (MPI_Request *solicitud, int *flag, MPI_Status *estado) MPI_Wait: bloquea al proceso hasta que finaliza la operación. MPI_Wait (MPI_Request *solicitud, MPI_Status *estado) Este tipo de comunicación permite solapar computo con comunicación. Evita overhead de manejo de buffer. Deja en manos del programador asegurar que se realice la comunicación correctamente. Clase 5 21-04-2015 25 Librería MPI - Comunicación no bloqueante punto a punto EJEMPLO: main (int argc, char *argv[]) { int cant, id, *dato, i; MPI_Status estado; dato = (int *) malloc (100 * sizeof(int)); MPI_Init(&argc,&argv); MPI_Comm_rank (MPI_COMM_WORLD, &id); if (id == 0) { cant = atoi(argv[1])%100; MPI_Send(dato,cant,MPI_INT,1,1,MPI_COMM_WORLD); for (i=0; i< 100; i++) dato[i]=0; } else { MPI_Recv(dato,100,MPI_INT,0,1,MPI_COMM_WORLD, &estado); MPI_Get_count(&estado, MPI_INT, &cant); //PROCESA LOS DATOS; }; MPI_Finalize; } Código usando comunicación bloqueante Para usar comunicación NO bloqueante (¿alcanza con cambiar el Send por Isend?) Clase 5 21-04-2015 26 Librería MPI - Comunicación no bloqueante punto a punto EJEMPLO: main (int argc, char *argv[]) { int cant, id, *dato, i; MPI_Status estado; MPI_Request req; dato = (int *) malloc (100 * sizeof(int)); MPI_Init(&argc,&argv); MPI_Comm_rank (MPI_COMM_WORLD, &id); if (id == 0) { cant = atoi(argv[1]); //INICIALIZA dato MPI_Isend(dato,cant,MPI_INT,1,1,MPI_COMM_WORLD, &req); //TRABAJA for (i=0; i< 100; i++) dato[i]=0; } else { MPI_Recv(dato,100,MPI_INT,0,1,MPI_COMM_WORLD, &estado); MPI_Get_count(&estado, MPI_INT, &cant); //PROCESA LOS DATOS; }; MPI_Finalize; } MPI_Wait(&req, &estado); Código anterior usando comunicación no bloqueante Clase 5 21-04-2015 27 Librería MPI - Comunicación no bloqueante punto a punto EJEMPLO: main (int argc, char *argv[]) { int id, *dato, i, flag; MPI_Status estado; MPI_Request req; dato = (int *) malloc (100 * sizeof(int)); MPI_Init(&argc,&argv); MPI_Comm_rank (MPI_COMM_WORLD, &id); if (id == 0) { //INICIALIZA dato MPI_Send(dato,cant,MPI_INT,1,1,MPI_COMM_WORLD); } else { MPI_Irecv(dato,100,MPI_INT,0,1,MPI_COMM_WORLD ,&req); MPI_Test(&req, &flag,&estado); while (!flag) { //Trabaja mientras espera MPI_Test(&req, &flag,&estado); }; //PROCESA LOS DATOS; }; MPI_Finalize; } Clase 5 21-04-2015 28 Librería MPI – Consulta de mensajes pendientes Información de un mensaje antes de hacer el Recv (Origen, Cantidad de elementos, Tag). MPI_Probe: bloquea el proceso hasta que llegue un mensaje que cumpla con el origen y el tag. MPI_Probe (int origen, int tag, MPI_Comm comunicador, MPI_Status *estado) MPI_Iprobe: cheqea por el arribo de un mensaje que cumpla con el origen y tag. MPI_Iprobe (int origen, int tag, MPI_Comm comunicador, int *flag, MPI_Status *estado) Comodines en Origen y Tag. ¿Cuando y porque usar cada uno? Clase 5 21-04-2015 29 Librería MPI - Comunicaciones Colectivas MPI provee un conjunto de funciones para realizar operaciones colectivas, sobre un grupo de procesos asociado con un comunicador. Todos los procesos del comunicador deben llamar a la rutina colectiva. Sincronización en una barrera. MPI_Barrier(MPI_Comm comunicador) Broadcast: un proceso envía el mismo mensaje a todos los otros procesos (incluso a él) del comunicador. MPI_Bcast (void *buf, int cantidad, MPI_Datatype tipoDato, int origen, MPI_Comm comunicador) Proceso 0 Proceso 1 Proceso 2 Proceso 3 Proceso 0 Proceso 1 Proceso 2 Proceso 3 Bcast Clase 5 21-04-2015 30 Librería MPI - Comunicaciones Colectivas (cont.) Reducción de todos a uno: combina los elementosenviados por cada uno de los procesos (inclusive el destino) aplicando una cierta operación. MPI_Reduce (void *sendbuf, void *recvbuf, int cantidad, MPI_Datatype tipoDato, MPI_Op operación, int destino , MPI_Comm comunicador) Proceso 0 Proceso 1 Proceso 2 Proceso 3 Proceso 0 Proceso 1 Proceso 2 Proceso 3 R ed u ce a 0 Clase 5 21-04-2015 31 Librería MPI - Comunicaciones Colectivas (cont.) Reducción de todos a todos: pone el resultado de una operación de reducción en todos los procesos. MPI_Allreduce (void *sendbuf, void *recvbuf, int cantidad, MPI_Datatype tipoDato, MPI_Op operación, MPI_Comm comunicador) Proceso 0 Proceso 1 Proceso 2 Proceso 3 Proceso 0 Proceso 1 Proceso 2 Proceso 3 All Reduce Clase 5 21-04-2015 32 Librería MPI - Comunicaciones Colectivas (cont.) Gather: recolecta el vector de datos de todos los procesos (inclusive el destino) y los concatena en orden para dejar el resultado en un único proceso. • Todos los vectores tienen igual tamaño. MPI_Gather (void *sendbuf, int cantEnvio, MPI_Datatype tipoDatoEnvio, void*recvbuf, int cantRec, MPI_Datatype tipoDatoRec, int destino, MPI_Comm comunicador) • Los vectores pueden tener diferente tamaño. MPI_Gatherv (void *sendbuf, int cantEnvio, MPI_Datatype tipoDatoEnvio, void*recvbuf, int *cantsRec, int *desplazamientos, MPI_Datatype tipoDatoRec, int destino, MPI_Comm comunicador) Proceso 0 Proceso 1 Proceso 2 Proceso 3 Proceso 0 Proceso 1 Proceso 2 Proceso 3 Gather a 0 Clase 5 21-04-2015 33 Librería MPI - Comunicaciones Colectivas (cont.) Gather de todos a todos: recolecta el vector de datos de todos los procesos y los concatena en orden para dejar el resultado en todos los procesos. • Todos los vectores tienen igual tamaño. MPI_AllGather (void *sendbuf, int cantEnvio, MPI_Datatype tipoDatoEnvio, void*recvbuf, int cantRec, MPI_Datatype tipoDatoRec, MPI_Comm comunicador) • Los vectores pueden tener diferente tamaño. MPI_Allgatherv (void *sendbuf, int cantEnvio, MPI_Datatype tipoDatoEnvio, void*recvbuf, int *cantsRec, int *desplazamientos, MPI_Datatype tipoDatoRec, MPI_Comm comunicador) Proceso 0 Proceso 1 Proceso 2 Proceso 3 Proceso 0 Proceso 1 Proceso 2 Proceso 3 All_Gather Clase 5 21-04-2015 34 Librería MPI - Comunicaciones Colectivas (cont.) Scatter: reparte un vector de datos entre todos los procesos (inclusive el mismo dueño del vector). • Reparte en forma equitativa (a todos la misma cantidad). MPI_Scatter (void *sendbuf, int cantEnvio, MPI_Datatype tipoDatoEnvio, void*recvbuf, int cantRec, MPI_Datatype tipoDatoRec, int origen, MPI_Comm comunicador) • Puede darle a cada proceso diferente cantidad de elementos. MPI_Scatterv (void *sendbuf, int *cantsEnvio, int *desplazamientos, MPI_Datatype tipoDatoEnvio, void*recvbuf, int cantRec, MPI_Datatype tipoDatoRec, int origen, MPI_Comm comunicador) Proceso 0 Proceso 1 Proceso 2 Proceso 3 Proceso 0 Proceso 1 Proceso 2 Proceso 3 Scatter de 0 Clase 5 21-04-2015 35 Librería MPI - Comunicaciones Colectivas (cont.) All to all: cada proceso envía una parte de sus datos a cada uno de los otros procesos (incluso a él) y recibe de ellos una parte (scatter + gather). • Todas las partes iguales. MPI_Alltoall (void *sendbuf, int cantEnvio, MPI_Datatype tipoDatoEnvio, void*recvbuf, int cantRec, MPI_Datatype tipoDatoRec, MPI_Comm comunicador) • Las distintas partes pueden tener diferente tamaño. MPI_Alltoallv (void *sendbuf, int *cantsEnvio, int *despEnvio, MPI_Datatype tipoDatoEnvio, void*recvbuf, int *cantsRec, int *despRec, MPI_Datatype tipoDatoRec, MPI_Comm comunicador) Proceso 0 Proceso 1 Proceso 2 Proceso 3 Proceso 0 Proceso 1 Proceso 2 Proceso 3 All_to_all Clase 5 21-04-2015 36 Librería MPI - Generación de comunicadores Hay veces que las comunicaciones deben restringirse a un subgrupo de procesos → generar nuevos comunicadores (por ejemplo para poder usar comunicaciones colectivas). Particionar comunicadores en subgrupos de procesadores según el valor de color. MPI_Comm_split (MPI_Comm comViejo, int color, int clave, MPI_Comm *comNuevo) Clase 5 21-04-2015 37 Librería MPI - Generación de comunicadores por Topologías Topologías cartesianas: permite reordenar los procesos formando k_d_mesh. Genera un nuevo comunicador con esa estructura. MPI_Cart_create (MPI_Comm comViejo, int numDim, int *tamDim, int *periodos, int reordenar, MPI_Comm comNuevo) • Cada proceso tiene un rank y sus coordenadas cartesianas. Hay dos funciones para convertir una identificación en otra. MPI_Cart_rank → dadas las coordenadas cartesianas retorna el rank. MPI_Cart_coords → dado el rank retorna las coordenadas cartesianas. Las topologías pueden dividirse formando nuevos comunicadores formando mesh de menos dimensiones. MPI_Cart_sub (MPI_Comm com_Cart, int *keep_dims, MPI_Comm *com_SubCart) • Se keep_dims[i] es TRUE (no cero en C) la ima dimensión se mantiene en la nueva sub-topología. Clase 5 21-04-2015 38 Librería MPI - Ejemplo de sub-tolpologías cartesianas Subdividiendo una topología cartesiana de 2 x 4 x 7 en (a) cuatro subgrupos de 2 x 1 x 7 y (b) ocho subgrupos de 1 x 1 x 7. Clase 5 PVM 21-04-2015 40 Librería PVM (Parallel Virtual Machine) Permite ver a un conjunto heterogéneo de computadoras como un único procesador paralelo de memoria distribuida. Proporciona las funciones necesarias para crear, comunicar y sincronizar sobre la máquina virtual. Aplicaciones escritas en C o FORTRAN. Modelo MPMD. Compuesto por un “Master” y varios “Slaves”. El Master activa a los Slaves. Configuración dinámica de la máquina virtual. Consola de PVM (para ejecución y configuración). Clase 5 21-04-2015 41 Librería PVM (Funciones de la Consola) Agregar máquinas → add host Eliminar máquinas → delete host Consultar configuración → conf host Salir de la consola → quit y halt Procesos en ejecución en la máquina virtual → ps –a Iniciar una aplicación PVM → spawn master Clase 5 21-04-2015 42 Librería PVM (Primitivas de control de procesos) Identificador del proceso. pvm_mytid() Activar procesos: activa n copias de tarea en host (si flag es 1) y devuelve la cantidad de procesos creados. int pvm_spawn(char *tarea, char **arg, int flag, char *host, n, int *tids) Matar procesos con tid id. pvm_kill(int id) Quitar de PVM el proceso llamante para que continúe su ejecución fuera de PVM. pvm_exit() Identificador del proceso padre. pvm_parent() Clase 5 21-04-2015 43 Librería PVM (Envió de mensajes) El envió de un mensaje involucra tres pasos: inicializar buffer, empaquetar datos en buffer, enviar buffer. Inicializar Buffer: crea un buffer vacío que pasa a ser el buffer activo. pvm_initsend(int codificación) codificación = PvmDataDefault Empaquetar datos en buffer: empaqueta n elementos de datos tomando los elementos de a pas pasos. pvm_pktipo(tipo *datos, int n, int pas) Envío individual: envía el contenido del buffer activo a otro proceso. pvm_send(int destino, int tag) Comodín = -1 Envío colectivo: envía el contenido del buffer activo a otros cantDest procesos. pvm_mcast(int *destinos, int cantDest, int tag) Clase 5 21-04-201544 Librería PVM (Recepción de mensajes) La recepción de un mensaje involucra dos pasos: recibir los datos en un buffer, desempaquetar los datos del buffer. Recepción de los datos: el proceso se bloquea hasta que recibe un mensaje de origen con tag. pvm_recv(int origen, int tag) Comodín = -1 Recepción no bloqueante: el proceso no se bloquea y si hay mensaje lo toma, sino sigue adelante. pvm_nrecv(int *origen, int tag) Desempaquetar datos del buffer: desempaqueta los datos en el buffer activo y los pone en dato. pvm_unpktipo(tipo *dato, int n, int pas) Clase 5 21-04-2015 45 Librería PVM (Configuración dinámica) Agregar hosts: agrega las n máquinas especificadas en nombres. pvm_addhost(char **nombres, int n, int *infos) Borrar hosts: elimina las n máquinas especificadas en nombres. pvm_delhost(char **nombres, int n, int *infos) Clase 5 21-04-2015 46 Librería PVM (Grupos de procesos) Añadir proceso llamante a grupo. pvm_joingroup (char *grupo) Sacar proceso llamante de grupo. pvm_lvgroup (char *grupo) Determinar el número de procesadores de grupo. pvm_gsize (char *grupo) Barrera que bloquea los procesos de grupo hasta que hayan llegado cant. pvm_barrier (char *grupo, int cant) Comunicación colectiva broadcast. pvm_bcast (char *grupo, int tag) Comunicación colectiva scatter: root reparte cant elementos de dato entre los procesos de grupo, poniéndolo en resultado. pvm_scatter (void *resultado, void *dato, int cant, int tipoDato, int tag, char *grupo, int root) Comunicación colectiva gather: root recoge en resultado los cant elementos que envía cada proceso de grupo en dato. pvm_gather(void *resultado, void *dato, int cant, int tipoDato, int tag, char *grupo, int destino) Clase 5 Reducir Overhead de Comunicación 21-04-2015 48 Minimizando los overheads de comunicación. Maximizar la localidad de datos. Minimizar el volumen de intercambio de datos. Minimizar la cantidad de comunicaciones. Considerar el costo de cada bloque de datos intercambiado. Replicar datos cuando sea conveniente. Lograr el overlapping de cómputo (procesamiento) y comunicaciones. En lo posible usar comunicaciones asincrónicas. Usar comunicaciones colectivas en lugar de punto a punto Clase 5
Compartir