1 / 104

Programación de Memoria Compartida

Programación de Memoria Compartida. openMP. El Modelo de Memoria Compartida. Los procesadores interactuan uno con otro mediante variables compartidas. OpenMP es el estandar para programaci ón de memoria compartida. ¿Que es openMP?.

caleb-bauer
Télécharger la présentation

Programación de Memoria Compartida

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. Programación de Memoria Compartida openMP

  2. El Modelo de Memoria Compartida Los procesadores interactuan uno con otro mediante variables compartidas. OpenMP es el estandar para programación de memoria compartida.

  3. ¿Que es openMP? • openMP es una especificación para una implementación portable de paralelismo en FORTRAN y C/C++. • La especificación provee directivos de compilador, rutinas de biblioteca que se pueden usar para controlar paralelismo.

  4. Paralelismo Fork/Join • Inicialmente solamente el hilo maestro está activo • El hilo maestro ejecuta el código secuencial • Fork: El hilo maestro crea hilos adicionales para ejecutar el código paralelo • Join: Al finalizar de código paralelo, los hilos creados mueren o se suspendien

  5. Ejemplo #include <omp.h> #include <stdio.h> int main (int argc, char *argv[]) { #pragma omp parallel printf(“Hello world\n”); return 0; }

  6. El Modelo de Memoria Compartida vs. el Modelo que Pasa Mensajes (#1) • El modelo de memoria compartida • El número de hilos es 1 al principio y al final y cambia dinámicamente durante de la ejecutación del programa • El Modelo que pasa mensajes • Todos los procesos estan activos durante de la ejecutacion del programa.

  7. Paralelización Incremental • Un programa secuencial es un caso especial de un programa de memoria compartida • Paralelización incremental es el procesos de convertir un programa secuencial a un programa paralelo poco a poco

  8. Un Bucle for Paralelo • Las iteraciones de un bucle for se pueden ejecutar en paralelo si ninguna iteración depende de otra anterior. • Ejemplos: Las iteraciones de - for (i=first;i<size;i += prime; marked[i]=1) se pueden ejecutar en paralelo, pero -for (i=1;i<=n;i++) suma += suma + v[i] no

  9. Pragmas • Una pragma en C o C++ es un directivo al compilador. • La sintaxis es #pragma omp <el resto de la pragma> Ejemplo: #pragma omp parallel for es una directriz que dice al compilador que trate a paralelizar el bucle for que sigue

  10. La Pragma for Paralelo #pragma omp parallel for for (i = 0; i < N; i++) a[i] = b[i] + c[i]; • El compilador tiene que verificar que cuando se ejecuta, habrá disponible la información necesaria para llevar a cabo las iteraciones

  11. La sintaxis de la pragma for paralelo

  12. El Contexto de Ejecutación • Todo hilo tiene un contexto de ejecutación, que consiste del espacio de direcciones que el hilo puede aceder • El contexto de ejecutación incluye variables estáticas, estructuras dinámicamente asignadas, y variables en el “run-time stack”

  13. “Variables Compartidas y Variables Privadas • Una variable compartida tiene la misma dirección en el contexto de ejecutación de cada hilo. • Una variable privada tiene una dirección distinta en el contexto de ejecutación de cada hilo. • Un hilo no puede aceder las variables privadas de otro hilo.

  14. Función omp_set_num_threads • Se usa para asignar el número de hilos a ser activos en secciones paralelas del código • Se puede llamar en varios puntos del programa void omp_set_num_threads (int t)

  15. omp_get_thread_num() • Todo hilo tiene una identificación que es el número del hilo • omp_get_thread_num()devuelve el número del hilo

  16. Función omp_get_num_procs • Devuelve el número de procesadores fisicos que están dispondible para el uso del programa paralelo int omp_get_num_procs (void)

  17. Hello World • #include <omp.h> • #include <stdio.h> • int main (int argc, char *argv[]) { • int p,th_id; • p=omp_get_num_procs(); • omp_set_num_threads(p); • #pragma omp parallel private(th_id); • { • th_id = omp_get_thread_num(); • printf("Hello World from thread %d\n", th_id); • } • return 0; • }

  18. Pragmas - REPASO • Una pragma en C o C++ es un directivo al compilador. • La sintaxis es #pragma omp <el resto de la pragma> Ejemplo: #pragma omp parallel for es una directriz que dice al compilador que trate a paralelizar el bucle for que sigue

  19. La sintaxis de la pragma for paralelo

  20. Ejemplo 1 #pragma omp parallel for for (i=0;i<(int) sqrt(x);i++) { a[i] = 2.3*i; if (i < 10) b[i]=a[i]; }

  21. Ejemplo 2 flag = 0; for (i=0;(i<n) & (!flag);i++){ a[i] = 2.3*i; if (a[i] < b[i]) flag = 1); } No se puede paralelizar el bucle pues no no satisface el requisito de sintaxis.

  22. Ejemplo 3 for (i=0;i<n;i++) { a[i] = foo(i); if (a[i] < b[i]) break; } No se puede paralelizar un bucle cuyo cuerpo contiene break, return, o exit.

  23. Variables privadas y compartidas • #pragma omp parallel <clausula> bloque • La clausula puede ser private (lista de variables) shared (lista de variables) y otras.

  24. Variables privadas y compartidas(2) • Una variable compartida tiene la misma dirección en el contexto de ejecutación de cada hilo • Una variable privada tiene una dirección distinta en el contexto de ejecutación de cada hilo • Cada variable en el cuerpo de un bucle paralelo, excepto la variable de iteración, que no se especifica como privada es compartida.

  25. Ejemplo //Despues de ejecutar el siguiente código, debe ser cierto que a[i] <= b[i] para todo i #pragma omp parallel for for (i=0;i<n;i++) if (a[i] > b[i]) {temp=a[i];a[i]=b[i]; b[i]=temp;} ¿Funciona este código?

  26. Ejemplo(continuado) • No funciona correctamente, pues la variable temp debe ser privada • //El código correcto #pragma omp parallel for private(temp) for (i=0;i<n;i++) if (a[i] > b[i]) {temp=a[i];a[i]=b[i]; b[i]=temp;}

  27. Grafos con Pesos • Un grafo dirigido en la cual hay asociado con cada arista un número positivo (el “peso”) se llama un grafo dirigido con pesos. • El largo de una trayectoria de un vértice u a otro vértice v es la suma de los pesos de las aristas que componen la trayectoria.

  28. El Problema de Todos Pares Distancias mas Cortas • Dado un grafo dirigido con pesos, ¿cuales son las trayectorias de largos mínimos (es decir “distancias mas cortas”) entre todos los pares de vértices?

  29. La Matríz de Adyacencias • Representar un grafo dirigido con pesos G con n vértices por una matríz AG como sigue: • Si 1,2, … ,n son los vértices, entonces el elemento en la fila #i y la columna #j es 0 si i=j, es ∞ (un número mas grande que cualquier peso) si no hay arista de I a j, y es el peso de la arista de i a j si tal arista existe. Llamemos AG la matríz de adyacencias.

  30. El Algoritmo de Floyd for (k= 0;k<n;k++) for (i =0;i< n;i++) for (j= 0;j<n;j++) a[i,j]  min (a[i,j], a[i,k] + a[k,j])

  31. A B C D E A 0 6 3 ∞ ∞ B 4 0 ∞ 1 ∞ C ∞ ∞ 0 5 1 D ∞ 3 ∞ 0 ∞ E ∞ ∞ ∞ 2 0 Ejemplo 4 A B 3 6 1 3 5 C 1 D 2 E Matríz de Adyacencias

  32. ¿Como se puede paralelizar el Algoritmo de Floyd para openMP? for (k= 0;k<n;k++) for (i =0;i< n;i++) for (j= 0;j<n;j++) a[i,j]  min (a[i,j], a[i,k] + a[k,j]) El bucle exterior no se puede paralelizar, pues las itereraciones no son independientes. Cada uno de los otros bucles es paralelizable.

  33. ¿Cual es el mejor? ¿Paralelizar el bucle en el medio o el mas interior? • Mejor paralelizar el bucle en el medio para Evitar el costo de multiplos fork-join.

  34. ¿Como se puede paralelizar el siguiente código? x[0] = complex_function(); for (i=0;j<n;i++) { for (j=1;j<4;j++) x[j]=g(i,x[j-1]); answer[i] = x[1] – x[3];}

  35. Como se puede paralelizar el siguiente código: x[0] = complex_function(); for (i=0;j<n;i++) { for (j=1;j<4;j++) x[j]=g(i,x[j-1]); answer[i] = x[1] – x[3];} Se puede hacer el bucle exterior paralelo si hacemos j y x privadas. Sin embargo, x[0] se necesita en la primera iteración del bucle interior.

  36. firstprivate Se podría mover la inicialización de x[0] a dentro del bucle anterior, pero es caro. Mejor usar la cláusula firstprivate. x[0] = complex_function(); #pragma omp parallel for private[j] firstprivate(x) for (i-0;j<n;i++) { for (j=1;j<4;j++) x[j]=g(i,x[j-1]); answer[i] = x[1] – x[3];}

  37. firstprivate Se podría mover la inicialización de x[0] a dentro del bucle anterior, pero es caro. Mejor usar la cláusula firstprivate. x[0] = complex_function(); #pragma omp parallel for private[j] firstprivate(x) for (i-0;j<n;i++) { for (j=1;j<4;j++) x[j]=g(i,x[j-1]); answer[i] = x[1] – x[3];}

  38. firstprivate (cont) • Se usa para crear una variable privada que tiene su valor inicial igual al valor de la variable controlada por el hilo maestro cuando se entra el bucle. • Si un hilo cambia el valor de una variable en alguna iteración, entonces este valor será el valor de la variable en iteraciones subsecuentes

  39. lastprivate • La secuencialmente última iteración es la última iteración que se lleva a cabo cuando el bucle se ejecuta secuencialmente • La cláusula lastprivate se usa para copiar el valor privado del hilo que ejecutó la secuencialmente última iteración a la copia del hilo maestro

  40. Ejemplo for (i=0;i<n;i++){ x[0] = 1.0; for (j=1;j<4;j++) x[j] = x[j-1] * (i+1); sum_of_powers[i] = x[0]+x[1]+x[2]+x[3]; } n_cubed = x[3]; Si se paraleliza el bucle exterior, no se puede predecir el valor de x[3]!

  41. Una solución para que x[3]=n3 #pragma omp parallel for private(j) lastprivate(x) for (i=0;i<n;i++){ x[0] = 1.0; for (j=1;j<4;j++) x[j] = x[j-1] * (i+1); sum_of_powers[i] = x[0]+x[1]+x[2]+x[3]; } n_cubed = x[3];

  42. La Regla Rectangulo para Computar  •  = ∫01 4/(1+x2) dx • La Regla de Rectangulo consiste de estimar el area debajo de la curva y=4/(1+x2) entre x=0 y x=1 mediante areas de rectangulos

  43. Código para aproximar  double area, pi, x; int i, n; ... area = 0.0; for (i = 0; i < n; i++) { x += (i+0.5)/n; area += 4.0/(1.0 + x*x); } pi = area / n;

  44. ¿Como se puede paralelizar el código para aproximar a ? for (i = 0; i < n; i++) { x += (i+0.5)/n; area += 4.0/(1.0 + x*x); } Si dos hilos, digamos A y B están ejecutando dos iteraciones, entonces B podria intentar a poner area al dia mientras que A está haciendo lo mismo, B podría usar el valor de area antes de que A ha terminado a poner su nuevo valor Esto se llama una “condición de carrera”

  45. La Pragma critical • #pragma omp critical bloque de código garantiza que solamente un hilo ejecuta el bloque a la vez

  46. Código correcto, pero no eficiente double area, pi, x; int i, n; ... area = 0.0; #pragma omp parallel for private(x) for (i = 0; i < n; i++) { x += (i+0.5)/n; #pragma omp critical area += 4.0/(1.0 + x*x); } pi = area / n;

  47. Ineficiente porque … Poner area al dia a dentro de una sección crítica no es eficiente ya que • Solamente un hilo puede ejecutar la asignación a la vez, es decir, es código secuencial. • El tiempo para ejecutarla puede ser una parte significativa del bucle

  48. Reducciones Se puede añadir una cláusula de reducción a una pragma parallel for Hay que especificar la operación y la variable OpenMP lleva cuenta de los resultados parciales y los combina despues de ejecutar el bucle

  49. La Cláusula reduction • La sintaxis es:reduction (<op> :<variable>) • Operadores + Suma * Producto & Bitwise and | Bitwise or ^ Bitwise exclusive or && Logical and || Logical or

  50. El Código  con la Cláusula reduction double area, pi, x; int i, n; ... area = 0.0; #pragma omp parallel for \ private(x) reduction(+:area) for (i = 0; i < n; i++) { x = (i + 0.5)/n; area += 4.0/(1.0 + x*x); } pi = area / n;

More Related