1 / 57

Arquitecturas Paralelas

Arquitecturas Paralelas. Arquitecturas Paralelas. IF - EHU. 9. Herramientas para la programación de aplicaciones paralelas: OpenMP y MPI (introducción) . Computadores de alta velocidad (la lista top500). Programación aplicaciones paralelas.

moriah
Télécharger la présentation

Arquitecturas Paralelas

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. Arquitecturas Paralelas Arquitecturas Paralelas IF - EHU 9.Herramientas para la programación de aplicaciones paralelas: OpenMP y MPI (introducción). Computadores de alta velocidad (la lista top500).

  2. Programación aplicaciones paralelas • Como sabemos, los sistemas paralelos MIMD presentan dos arquitecturas diferenciadas: memoria compartida y memoria distribuida. El modelo de memoria utilizado hace que la programación de aplicaciones paralelas para cada caso sea esencialmente diferente.

  3. Programación aplicaciones paralelas Para los sistemas de memoria compartida tipo SMP, la herramienta más utilizada esOpenMP. • Para los sistemas de memoria distribuida (MPP), el “estándar” de programación, mediante paso de mensajes, es MPI. Otras opciones: UPC (Unified Parallel C) shrmem (Cray) Tarjetas gráficas: CUDA / OpenCL

  4. Programación aplicaciones paralelas EarthSimulator

  5. OpenMP • una pequeña introducción

  6. Introducción • OpenMP es el estándar actual para programar aplicaciones paralelas en sistemas de memoria compartida. No se trata de un nuevo lenguaje de programación, sino de un API (application programming interface) formado por: directivas para el compilador (C)#pragma omp <directiva> unas pocas funciones de biblioteca algunas variables de entorno

  7. thread master thread master región paralela Introducción • El modelo de programación paralela que aplica OpenMP es Fork - Join. • En un determinado momento, el thread master genera P threads que se ejecutan en paralelo. FORK JOIN

  8. Introducción • Todos los threads ejecutan la misma copiadel código (SPMD). A cada thread se le asigna un identificador (tid). • Para diferenciar las tareas ejecutadas por cada thread: • if (tid == 0) then ... else ... •  constructores específicos de reparto de tareas (work sharing).

  9. Introducción • En resumen, partiendo de un programa serie, para obtener un programa paralelo OpenMP hay que añadir: • directivasque especifican una región paralela (código replicado), reparto de tareas (específicas para cada thread), o sincronización entre threads. • funciones de biblioteca (include <omp.h>): para gestionar o sincronizar los threads..

  10. Ejemplo main () { for (i=0; i<1000; i++) { A[i] = A[i] +1; B = B + A[i]; } printf(“ B = %d\n”, B); } #pragma omp parallel private(tid) { } tid = omp_get_thread_num(); printf (“ thread %d en marcha \n”, tid); #pragma omp for schedule(static) reduction(+:B) if (tid==0)

  11. Conceptos básicos • 0Procesos paralelos (threads). • 1REGIONES PARALELAS. Ámbito de las variables. • 2REPARTO DE TAREAS. • Datos: bucles for. Reparto de iteraciones. • Funciones: sections / single / ... • 3SINCRONIZACIÓN. • Secciones críticas, cerrojos, barreras.

  12. Conceptos básicos • 0Número de threads  estático, una variable de entorno:: > export OMP_NUM_THREADS = 10  dinámico, mediante una función: omp_set_num_threads (10); 0¿Quién soy / cuántos somos? tid = omp_get_thread_num(); nth = omp_get_num_threads();

  13. Regiones paralelas • 1REGIÓN PARALELA(parallel regions) • # pragma omp parallel [VAR,...] • { código } • Una región paralela es un trozo de código que se va a repetir y ejecutar en paralelo en todos los threads. • Las variables de una región paralela pueden sercompartidas (shared) o privadas (private).

  14. barrera Regiones paralelas • > Un ejemplo sencillo: ... #define N 12 int i, tid, nth, A[N]; main () { for (i=0; i<N; i++) A[i]=0; #pragma omp parallel { nth = omp_get_num_threads (); tid = omp_get_thread_num (); printf ("Thread %d de %d en marcha \n", tid, nth); A[tid] = 10 + tid; printf (" El thread %d ha terminado \n", tid); } for (i=0;i<N;i++) printf (“A(%d)=%d\n”,i,A[i]); } private(tid,nth) shared(A)

  15. Reparto de tareas: bucles • 2REPARTO DE TAREAS: bucles • Los bucles son uno de los puntos de los que extraer paralelismo de manera “sencilla” (paralelismo de datos (domain decomposition) de grano fino). • Obviamente, la simple replicación de código no es suficiente. Por ejemplo, #pragma omp parallel shared(A) private(i) { for (i=0; i<100; i++) A[i] = A[i] + 1; } ?

  16. Reparto de tareas: bucles • Tendríamos que hacer algo así: #pragma omp parallel shared(A) private(tid,nth,ini,fin,i) {tid = omp_get_thread_num(); nth = omp_get_num_threads(); ini = tid * 100/nth; fin = (tid+1) * 100/nth; for (i=ini; i<fin; i++) A[i] = A[i] + 1; } ! El reparto de bucles se realiza automáticamente con la directiva pragma omp for.

  17. ámbito variables reparto iteraciones sincronización 0..24 barrera 25..49 50..74 75..99 Reparto de tareas: bucles #pragma omp parallel [...] {… #pragma omp for [clausulas] for (i=0;i<100;i++)A[i]=A[i]+1; … }

  18. #pragma omp parallel for private (i,j,X) for (i=0; i<N; i++) for (j=0; j<M; j++) { X = B[i][j] * B[i][j]; A[i][j] = A[i][j] + X; C[i][j] = X * 2 + 1; } Reparto de tareas: bucles • for (i=0; i<N; i++) • for (j=0; j<M; j++) • { • X = B[i][j] * B[i][j]; • A[i][j] = A[i][j] + X; • C[i][j] = X * 2 + 1; • } Se ejecutará en paralelo el bucleexterno, y los threads ejecutaránel bucle interno. Paralelismo de grano “medio”. Las variables i,jyXse declaran como privadas.

  19. for (i=0; i<N; i++) #pragma omp parallel for private (j,X) for (j=0; j<M; j++) { X = B[i][j] * B[i][j]; A[i][j] = A[i][j] + X; C[i][j] = X * 2 + 1; } Reparto de tareas: bucles • for (i=0; i<N; i++) • for (j=0; j<M; j++) • { • X = B[i][j] * B[i][j]; • A[i][j] = A[i][j] + X; • C[i][j] = X * 2 + 1; • } Los threads ejecutarán en paralelo el bucle interno (el externo se ejecuta en serie). Paralelismo de grano fino. Las variables j y Xse declaran como privadas.

  20. Reparto de las iteraciones •  ¿Cómo se reparten las iteraciones de un bucle entre los threads? • Puesto que el pragma for termina con una barrera, si la carga de los threads está mal equilibrada tendremos una pérdida (notable) de eficiencia. La cláusula schedulepermite definir diferentes estrategias de reparto, tanto estáticas como dinámicas.

  21. Reparto de las iteraciones • > Ejemplo #pragma omp parallel for shared(A)private(i) schedule(static,2) for (i=0; i<32; i++) A[i] = A[i] + 1; pid iteraciones 0: 0,1,8,9,16,17,24,25 1: 2,3,10,11,18,19,26,27 2: 4,5,12,13,20,21,28,29 3: 6,7,14,15,22,23,30,31 Recuerda: estático menos coste / mejor localidad datos dinámico más coste / carga más equilibrada

  22. fun1 fun2 fun3 pragma omp sections Rep.de tareas: funciones 2REPARTO DE TAREAS: funciones También puede usarse paralelismo de función (function decomposition), mediante la directiva sections. #pragma omp parallel [clausulas] { #pragma omp sections [clausulas] { #pragma omp section fun1(); #pragma omp section fun2(); #pragma omp section fun3(); } }

  23. Rep.de tareas: funciones 2REPARTO DE TAREAS: funciones Dentro de una región paralela, la directiva single asigna una tarea a un único thread. Sólo la ejecutará un thread, pero no sabemos cúal.

  24. Sincronización de threads • 3 SINCRONIZACIÓN • Cuando no pueden eliminarse las dependencias de datos entre los threads, entonces es necesario sincronizar su ejecución. OpenMP proporciona los mecanismos de sincronización más habituales: exclusión mutua y sincronización por eventos.

  25. Sincronización de threads • a. Secciones críticas: pragma omp critical #pragma omp parallel for for (i=0; i<N; i++) { A[i] = fun(i); if (A[i]>MAX) #pragma omp critical(SMAX) { if (A[i]>MAX) MAX = A[i]; } if (A[i]<MIN) #pragma omp critical(SMIN) { if (A[i]<MIN) MIN = A[i]; } } Por ejemplo, calcular el máximo y el mínimo de los elementos de un vector.

  26. Sincronización de threads • a.Secciones críticas: pragma omp atomic Una sección crítica para una operación simple de tipo RMW. Por ejemplo, #pragma omp parallel ... { ... #pragma omp atomic X = X + 1; ... }

  27. Sincronización de threads • b.Cerrojos • - omp_set_lock (&C) • espera a que el cerrojo C esté abierto; en ese momento, cierra el cerrojo en modo atómico. • - omp_unset_lock (&C) • abre el cerrojo C. • - omp_test_lock (&C) • testea el valor del cerrojo C; devuelve T/F.

  28. Sincronización de threads • > Ejemplo #pragma omp parallel private(nire_it) { omp_set_lock(&C1); mi_it = i; i = i + 1; omp_unset_lock(&C1); while (mi_it<N) { A[mi_it] = A[mi_it] +1; omp_set_lock(&C1); mi_it = i; i = i + 1; omp_unset_lock(&C1); } }

  29. #pragma omp barrier Sincronización de threads c. Barreras:pragma omp barrier #pragma omp parallel private(tid) { tid = omp_get_thread_num(); A[tid] = fun(tid); #pragma omp for for (i=0; i<N; i++) B[i] = fun(A,i); #pragma omp for for (i=0; i<N; i++) C[i] = fun(A,B,i); D[tid] = fun(tid); } nowait

  30. Resumen  Variables de entorno y funciones (núm. de hilos, identificadores...)  Directiva para definir regiones paralelas #pragma omp parallel [var…]  Directivas de reparto de tareas #pragma omp for [var,sched…] #pragma omp sections [var]  Directivas y funciones de sincronización #pragma omp critical [c] / atomic #pragma omp barrier cerrojos(set_lock,unset_lock,test_lock)

  31. Más información TEXTOS •R. Chandra et al.: Parallel Programming in OpenMPMorgan Kaufmann, 2001. WEB •www.openmp.org (especificación 3.0, software…) COMPILADORES •de pago •libres: p. e., el compilador de C/C++ de Intel

  32. MPI • una pequeña introducción

  33. Introducción Si para los sistemas SMP la opción es OpenMP, el “estándar” actual de programación de los sistemas de memoria distribuida, mediante paso de mensajes, es MPI (message-passing interface). MPI es, básicamente, una librería (grande) de funciones de comunicación para el envío y recepción de mensajes entre procesos. MPI indica explicitamente la comunicación entre procesos, es decir: -- los movimientos de datos -- la sincronización

  34. Tipos de comunicación Dos tipos de comunicación: • punto a punto• global El modelo de paralelismo que implementa MPI es SPMD. if (pid == 1) ENVIAR_a_pid2 else if (pid == 2) RECIBIR_de_pid1 Recuerda: cada proceso dispone de su propio espacio independiente de direcciones.

  35. Tipos de comunicación Modos de comunicación (1) •síncrona La comunicación no se produce hasta que emisor y receptor se ponen de acuerdo. • mediante un búfer 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.

  36. Tipos de comunicación Modos de comunicación (2) •bloqueante Se espera a que la comunicación se produzca. La comunicación síncrona es siempre bloqueante. En el caso buffered,existen ambas alternativas. • no bloqueante Se retorna y se continúa con la ejecución. Más adelante, se comprueba si la comunicación ya se ha efectuado.

  37. Tipos de comunicación Cada estrategia tiene sus ventajas e inconvenientes: > síncrona: es más rápida si el receptor está dispuesto a recibir; nos ahorramos la copia en el buffer. Además del intercambio de datos, sirve para sincronizar los procesos. Ojo: al ser bloqueante es posible un deadlock! > buffered: el emisor no se bloquea si el receptor no está disponible, pero hay que hacer copia(s) del mensaje (más lento).

  38. Introducción MPI gestiona los procesos estáticamente (número y asignación) (MPI2 también dinámicamente). Cada proceso tiene un identificador opid.  MPI agrupa los procesos implicados en una ejecución paralela en “comunicadores”. Un comunicador agrupa a procesos que pueden intercambiarse mensajes. El comunicador MPI_COMM_WORLD está creado por defecto y engloba a todos los procesos.

  39. Funciones básicas Aunque MPI consta de más de 300 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(…)

  40. 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.

  41. F. básicas: Comm_rank / _size 2.Identificación de procesos • > MPI_Comm_rank(comm,&pid); • Devuelve en pid el identificador del proceso dentro del comunicador comm especificado. • Los procesos se identifican mediante dos parámetros: el pid y el grupo (comm,p.e., MPI_COMM_WORLD). • > MPI_Comm_size(comm,&npr); • Devuelve en npr el número de procesos del comunicador comm.

  42. Funciones básicas Un ejemplo sencillo #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(“Proc. %d de %d activado, A = %d\n”, pid,npr,A); MPI_Finalize(); }

  43. A B enviar recibir F. básicas: Send / Receive 3.Envío y recepción de mensajes La comunicación entre procesos necesita (al menos) de dos participantes: el emisor y el receptor. El emisor ejecuta la función de envío de mensajes, y el receptor la de recepción. La comunicación es un proceso cooperativo. Si una de las dos funciones no se ejecuta, la comunicación no tiene lugar (y podría producirse un deadlock!).

  44. F. básicas: Send / Receive Función básica para enviar un mensaje: > MPI_Send(&mess,count,type,dest, tag,comm); - mensaje: [mess(@com), count(tamaño), type] - receptor: [dest, comm(grupo)] - tag: dato de control, de 0 a 32767 (tipo de mensaje, orden...)

  45. F. básicas: Send / Receive Función básica para recibir un mensaje: > MPI_Recv(&mess,count,type,source, tag,comm,&status); - mensaje (espacio): [mess, count, type] - emisor: [source, comm] - tag: clase de mensaje... - status:información de control sobre el mensaje recibido Recvse bloquea hasta que se recibe el mensaje.

  46. 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,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, N, MPI_INT, orig, tag, MPI_COMM_WORLD, &info); MPI_Get_count(&info,MPI_INT,&ndat); printf(“Datos de 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(); }

  47. Más tipos de Send / Receive • Síncrono: • MPI_Ssend(&mes,count,datatype,dest,tag,comm); • Ssend no devuelve control hasta que el receptor comienza la lectura. Inmediato: MPI_Isend (...); Retorna nada más ejecutarse; luego, para saber si se ha producido o no la comunicación: MPI_Test (...) devuelve 0 o 1 MPI_Wait (...)espera a que finalice

  48. Comunicaciones colectivas •  Muchas aplicaciones requieren de operaciones de comunicación en las que participan muchos procesos. • La comunicación es colectiva si participan en ella todos los procesos del comunicador.  Ejemplo: un broadcast, envío de datos desde un proceso a todos los demás. ¿Uno a uno en un bucle?

  49. Comunicaciones colectivas •  Las funciones de comunicación colectiva son bloqueantes. • Todos los procesos que forman parte del comunicador deben ejecutar la función. Tres tipos 1 Movimiento de datos 2 Operaciones en grupo 3 Sincronización

  50. A P0 A P1 P0 A P1 A P2 P3 P2 P3 A CC: movimento de datos • 1a Broadcast: envío de datos desde un proceso (root) a todos los demás. > MPI_Bcast(&mess,count,type,root,comm); (implementación logarítmica en árbol)

More Related