Programación Paralela en OpenMp Proyecto PAPIME PE104911 Facultad de Ingeniería Universidad Nacional Autónoma de México 1
Utilidad de realizar procesamiento paralelo en computadoras con arquitectura de memoria compartida que permitan la ejecución simultanea de varios hilos. 2
Memoria compartida En el hardware de una computadora, la memoria compartida se refiere a un bloque de memoria de acceso aleatorio a la que se puede acceder por varias unidades de procesamiento diferentes. 3
Memoria Compartida En software, la memoria compartida Es un método de comunicación entre procesos/hilos, es decir, una manera de intercambiar datos entre programas que se ejecutan al mismo tiempo. Un proceso creará un espacio en la memoria RAM a la que otros procesos pueden tener acceso. 4
Arquitectura de Memoria Compartida Casi todas las computadoras actuales cuentan con una arquitectura de memoria compartida con múltiples unidades de procesamiento conectadas a la misma memoria física. 5
Multicore La carrera de creación de procesadores cada vez más rápidos sufrió un punto de inflexión con la aparición de procesadores con arquitectura multicore. Esta arquitectura permitía frenar la escalada de consumo de potencia. Las arquitecturas multicore permiten obtener un rendimiento equivalente sin la contraprestación del consumo y esto ha provocado un gran desarrollo en los últimos años. Ejemplo Samsung Galaxy S4 con un procesador con 8 cores. 6
Multicore Para poder aprovechar la potencia que ofrecen estos procesadores los desarrolladores de software deben transformar las actuales aplicaciones secuenciales en paralelas. 7
Referencia para diseño de programas paralelos Seguir etapas de diseño de un programa paralelo (Ian- Foster) http://www.mcs.anl.gov/~itf/dbpp/ The Multicore Association en su Multicore Programming Practices ofrece un método para escribir software en arquitecturas multicore utilizando Cy C++ Algunos integrantes: CriticalBlue, Freescale, Intel, PolyCore Software, Texas Instruments, Wind River s Virtutech subsidiary. 8
Etapas de Diseño Aplicar las etapas en el diseño de programas paralelos : Particionamiento Comunicación Aglomeración Mapeo Particionamiento Aglomeración Comunicación Mapeo 9
Etapas de fase de diseño Particionamiento (descomposición de tareas). Detección de niveles de paralelismo y granularidad; así como de algoritmos paralelos. Comunicación (estructura necesaria para coordinar la ejecución). Manejo de alta cohesión y bajo acoplamiento entre subprocesos. Aglomeración: Evaluación de tareas y estructura con respecto al rendimiento y costo, combinando tareas para mejorar. Aplicación de paradigmas de programación paralela. Mapeo. (asignación de tareas a unidades de procesamiento). Decisión de la distribución de los procesos en los procesadores 10
Fase Diseño V1 particionamiento comunicación problema tareas subprocesos con comunicación 11
Fase Diseño V1 aglomeración mapeo subprocesos con comunicación programas paralelos Paradigmas de programación paralela procesadores Planificación de procesos 12
Fase Diseño V2 13
Multicore Programming Practices Aborda un conjunto de fases con el objetivo de parelelizar una aplicación: Análisis de la aplicación y diseño de alto nivel: el objetivo de esta fase es analizar las características de la aplicación. Implementaciony diseño de bajo nivel:selección de los patrones de diseño, algoritmos y estructuras de datos para la posterior codificación de la concurrencia necesaria. Depuración: La introducción de concurrencia implica condiciones especiales en la depuración del código. Rendimiento: Es un proceso de optimización en el que se analiza la mejora del rendimiento conseguido, identificando nuevos cuellos de botella en la ejecución del código, incluyendo comunicaciones, sincronización, bloqueos, equilibrado de carga y ubicación de los datos. 14
Particionamiento o Descomposición Descomposición de dominio o datos Descomposición funcional o tareas 15
Descomposición de dominio Encontrar el elemento mayor en un arreglo de enteros Primero se trabaja en la división de los datos y después es el cómputo asociado 16
Descomposición de dominio Encontrar el elemento mayor en un arreglo de enteros CPU 0 CPU 1 CPU 2 CPU 3 17
Descomposición de dominio Encontrar el elemento mayor en un arreglo de enteros CPU 0 CPU 1 CPU 2 CPU 3 18
Descomposición de dominio Encontrar el elemento mayor en un arreglo de enteros CPU 0 CPU 1 CPU 2 CPU 3 19
Descomposición de dominio Encontrar el elemento mayor en un arreglo de enteros CPU 0 CPU 1 CPU 2 CPU 3 20
Descomposición de dominio Encontrar el elemento mayor en un arreglo de enteros CPU 0 CPU 1 CPU 2 CPU 3 21
Descomposición de dominio Encontrar el elemento mayor en un arreglo de enteros CPU 0 CPU 1 CPU 2 CPU 3 Elba Karen Sáenz García- Oscar René Valdez 22
Descomposición de dominio Encontrar el elemento mayor en un arreglo de enteros CPU 0 CPU 1 CPU 2 CPU 3 23
Descomposición de dominio Encontrar el elemento mayor en un arreglo de enteros CPU 0 CPU 1 CPU 2 CPU 3 24
Descomposición de dominio Encontrar el elemento mayor en un arreglo de enteros CPU 0 CPU 1 CPU 2 CPU 3 25
Descomposición de dominio Encontrar el elemento mayor en un arreglo de enteros CPU 0 CPU 1 CPU 2 CPU 3 26
Descomposición de dominio Encontrar el elemento mayor en un arreglo de enteros CPU 0 CPU 1 CPU 2 CPU 3 27
Descomposición Funcional Primero se trabaja en la división de tareas o funciones y despues en los datos asociados a cada tarea 28
Descomposición Funcional f() g() h() q() r() s() 29
Descomposición Funcional CPU 1 CPU 0 f() g() CPU 2 h() q() r() s() 30
Descomposición Funcional CPU 1 CPU 0 f() g() CPU 2 h() q() r() s() 31
Descomposición Funcional CPU 1 CPU 0 f() g() CPU 2 h() q() r() s() 32
Descomposición Funcional CPU 1 CPU 0 f() g() CPU 2 h() q() r() s() 33
Descomposición Funcional CPU 1 CPU 0 f() g() CPU 2 h() q() r() s() 34
Descomposición pipilined 35
Gráfica de dependencias Grafica = (nodo, flecha) Nodo por cada variable (excepto variables índice) Constante Operador o función Flechas indican uso de variables y constantes 36
for (i = 0; i < 3; i++) a[i] = b[i] / 2.0; Gráfica de dependencias Ejemplo #1 b[0] 2 b[1] 2 b[2] 2 / / / a[0] a[1] a[2] 37
for (i = 0; i < 3; i++) a[i] = b[i] / 2.0; Gráfica de dependencias Ejemplo #1 b[0] 2 b[1] 2 b[2] 2 / / / a[0] a[1] a[2] 38
for (i = 1; i < 4; i++) a[i] = a[i-1] * b[i]; Gráfica de dependencias Ejemplo #2 a[0] b[1] b[2] b[3] * * * a[1] a[2] a[3] 39
for (i = 1; i < 4; i++) a[i] = a[i-1] * b[i]; Gráfica de dependencias Ejemplo #2 a[0] b[1] b[2] b[3] * * * a[1] a[2] a[3] 40
a = f(x, y, z); b = g(w, x); t = a + b; c = h(z); s = t / c; Gráfica de dependencias Ejemplo #3 w x y z g b f a h c t / s 41
a = f(x, y, z); b = g(w, x); t = a + b; c = h(z); s = t / c; Gráfica de dependencias Ejemplo #3 w x y z g b f a h c t / s 42
Gráfica de dependencias for (i = 0; i < 3; i++) a[i] = a[i] / 2.0; Ejemplo #4 a[0] 2 a[1] 2 a[2] 2 / / / a[0] a[1] a[2] 43
for (i = 0; i < 3; i++) a[i] = a[i] / 2.0; Gráfica de dependencias Ejemplo #4 a[0] 2 a[1] 2 a[2] 2 / / / a[0] a[1] a[2] 44
Otros ejemplos 45
Es posible encontrar paralelismo? Renderizar una foto Búsqueda de una palabra en un documento Actualizar una hoja de cálculo Compilar un programa 46
Conceptos de Paralelismo 47
Paralelismo Existen dos visiones del paralelismo: Paralelismo Hardware: definido por la arquitectura de la máquina Paralelismo Software: Definido por la estructura del programa. Se manifiesta en las instrucciones que no tienen dependencia 48
Niveles de paralelismo Paralelismo a nivel de tarea o trabajo: Diferentes tareas se ejecutan simultáneamente en diferentes Unidades de procesamiento (UP). Paralelismo a nivel de programa: Dividir tarea en subtareas y asignarlas a diferentes UP. Paralelismo a nivel de instrucción: Ejecutar instrucciones independientes en forma simultánea. Paralelismo a nivel de bit: De bajo nivel, se logra a través del hardware 49
Concurrencia y paralelismo Programa concurrente: Es aquél que define acciones que pueden realizarse simultáneamente Programa paralelo: Es un programa concurrente diseñado para su ejecución en un hardware paralelo Programa distribuido: Es un programa paralelo diseñado para su ejecución en una red de procesadores autónomos que no comparten la memoria 50
Modelos de programación Shared Memory Threads Distributed Memory / Message Passing Data Parallel Hybrid Single Program Multiple Data (SPMD) Multiple Program Multiple Data (MPMD) 51
Alternativas para modelo de memoria compartida En el caso de memoria compartida. trabajar con procesos (UNIX) usar threads: Pthreads (POSIX), Java, OpenMP 52
Introducción a Open Multiprocessing (OpenMP) Proyecto PAPIME PE104911 53
Qué es OpenMP? API para programación multiproceso en computadoras con arquitectura de memoria compartida, en múltiples plataformas. Formada por directivas del compilador bibliotecas de funciones variables de ambiente, No un lenguaje. Basado en el modelo de hilos. 54
Open MP Definido por un grupo de proveedores de hardware y de software AMD (OpenMP ARB 1997) BCS - Barcelona Supercomputing Center CAPS-Entreprise Convey Computer Cray Fujitsu HP IBM Intel Microsoft NEC NVIDIA Oracle Corporation Signalogic The Portland Group, Inc. Texas Instruments Mas información en www.openmp.org 55
Qué es OpenMP? Modelo de programación paralelo. Paralelismo de memoria compartida. Extensiones para lenguajes de programación existentes (C,C++, Fortran) Combina código serial y paralelo en un solo archivo fuente. 56
Algunos Compiladores Compañía Compilador Información GNU gcc Usado en Linux, Solaris, AIX, MacOSX, Windows OpenMP 3.1 y soportado desde GCC 4.7 IBM XL C/C++ / Fortran fopenmp Usado en AIX y Linux. Oracle C/C++ / Fortran Solaris y Linux Intel C/C++ / Fortran (10.1) Windows, Linux y MacOSX. /Qopenmp y -openmp 57
Algunas preguntas Qué es un proceso? Qué es un hilo? Qué se comparte entre los hilos? Cuál es la diferencia entre hilo y proceso? 58
Proceso Programa en algún estado en ejecución. Poseen espacios de memoria independientes Los cambios de estado (cambios de contexto) son relativamente costosos en términos de tiempo. 59
Estados de un proceso 60
Estados de un proceso En un principio, un proceso no existe. Una vez creado el proceso pasa al estado denominado Listo(está en condiciones de hacer uso de la CPU en cuanto se le dé la oportunidad. Un proceso puede pasar de Ejecución a Bloqueado cuando ha de esperar porque ocurra un determinado evento o suceso. Espera por la terminación de una operación de E/S o finalización de otra tarea de otro proceso 61
Hilos (Thread) Dentro de un proceso puede haber varios hilos de ejecución. Un hilo, también llamado hebra, proceso ligero, flujo, subproceso o thread es un programa en ejecución que comparte la imagen de memoria y otros recursos del proceso con otros hilos. Por tanto, un hilo puede definirse como cada secuencia de control dentro de un proceso que ejecuta sus instrucciones de forma independiente. 62
Procesos con un solo hilo y con múltiples hilos Código Datos Archivos Código Datos Archivos Hilo Hilos Mono-hilo Multi-hilo 63
Hilos y procesos un proceso un hilo un proceso varios hilos varios procesos un hilo por proceso varios procesos varios hilos por proceso 64
Empezando con OpenMP Proyecto PAPIME PE104911 65
Arquitectura de OpenMP Fork/join (Maestro esclavo) Trabajo Y Datos Compartido entre hilos Maneja sincronización (barreras, otras) 66
Fork / Join F O R K J O I N F O R K J O I N Master Thread Parallel Regions 67
Sintaxis Directivas o pragmas #pragma omp construct [clause [clause] ] Clausulas: Especifican atributos para compartir datos y calendarización Una pragma en C o C++ es un directivo al compilador. 68
Regiones paralelas Master Thread #pragma omp parallel Thread 1 Thread 2 Thread 3 Implicit Barrier 69
Regiones paralelas Los hilos son creados desde el pragma parallel. Los datos son compartidos entre los hilos. C/C++ : #pragma omp parallel { bloque código } 70
Cuántos hilos? Num. Hilos = Num. Procesadores o núcleos Intel lo usa de esta forma. Se definen más hilos con la variable de ambiente OMP_NUM_THREADS. 71
Actividad 1 Compilar la versión serial. #include <stdio.h> int main() { int i; printf( Hola Mundo\n"); for(i=0;i<6;i++) printf("iter:%d\n",i); } printf( Adios \n"); 72
Actividad 1 Agregar la directiva para ejecutar las primeras cuatro líneas del main en paralelo. Compilar con la opción -fopenmp Qué sucede? 73
Actividad 2 Aumentar el número de hilos a 4 y ejecutar el programa $ export OMP_NUM_THREADS=4 Ejecutar el programa con más hilos y describir lo que sucede. 74
Regiones paralelas Número de hilos en la región paralela El número de hilos que se generan para ejecutar una región paralela se controla: a. estáticamente, mediante una variable de entorno: > export OMP_NUM_THREADS=4 b. en ejecución, mediante una función : omp_set_num_threads(4); c. en ejecución, mediante una cláusula del pragma parallel : num_threads(4) 75
Work Sharing constructor for #pragma omp paralell #pragma omp for for(i=0;i<100;i++) { Realizar Trabajo(); } Divide las iteraciones entre los hilos. Debe estar especificada en una región paralela 76
#pragma omp parallel #pragma omp for for(i = 0; i < 12; i++) c[i] = a[i] + b[i] #pragma omp parallel #pragma omp for i = 0 i = 1 i = 2 i = 3 i = 4 i = 5 i = 6 i = 7 i = 8 i = 9 i = 10 i = 11 Implicit barrier 77
Combinando Pragmas Estos dos segmentos de código son equivalentes. #pragma omp parallel { #pragma omp for for (i=0; i< MAX; i++) { res[i] = huge(); } } #pragma omp parallel for for (i=0; i< MAX; i++) { res[i] = huge(); } 78
Actividad Modificar el programa de la actividad 1 para dividir el número de iteraciones entre los hilos. 79
Regiones paralelas Variables Compartidas y Privadas El hilo maestro tiene como contexto el conjunto de variables del programa, y existe a lo largo de toda la ejecución del programa. Al crearse nuevos hilos, cada uno incluye su propio contexto, con su propia pila, utilizada como stack frame para las rutinas invocadas por el hilo Las variables definidas por el hilo maestro son compartidas por todos los hilos. Sin embargo, algunas variables deberán ser propias de cada, privadas.. 80
Condiciones de carrera Una condición de carrera (race condition) ocurre cuando dos o mas hilos acceden a un recurso compartido sin control. Lo más común es el conflicto en el almacenamiento Acceso concurrente de la misma dirección de memoria por varios hilos Al menos un hilo está escribiendo 81
Variables Compartidas y Privadas Thread Private Variables Shared Variables Private Variables Thread Shared-Memory Model and Threads 82
Ejemplo descomposición de dominio código secuencial: int a[1000], i; for (i = 0; i < 1000; i++) a[i]=foo(i); Thread 0: for (i=0;i<500; i++) a[i] = foo(i); Thread 1: for (i=500;i<1000; i++) a[i] = foo(i); Private Shared 83
Descomposición Funcional volatile int e; main () { int x[10], j, k, m; j = f(x, k); m = g(x. k); } Variables locales a funciones: Private int f(int *x, int k) { Thread 0 int a; a = e * x[k] * x[k]; return a; } int g(int *x, int k) { Thread 1 int a; k = k-1; a = e / x[k]; return a; } 84
shared(x) Clausulas Se declara la variable X como compartida por todos los hilos. Sólo existe una copia, y todos los hilos acceden y modifican dicha copia. private(y) R.P.: Cláusulas de ámbito Se declara la variable Y como privada en cada hilo. Se crean P copias, una por hilo(sin inicializar!). Se destruyen al finalizar la ejecución de los hilos. 85
Ejemplo Realizar un programa que sume dos arreglos unidimensionales y los almacene en un tercer arreglo. float x, y; int I, c[n]; #pragma omp parallel for private(x,y) for(i=0; i<n; i++) { x = a[i]; y = b[i]; c[i] = x + y; } 86
Ejemplo problemas con private Se requiere realizar el producto entre dos vectores de dimensión n. float prod_punto(float* a, float* b, int N) { float sum = 0.0; #pragma omp parallel for for (int i=0; i<n; i++) { sum += a[i] * b[i]; } return sum; } 87
Funciones de ambiente void omp_set_num_threads(int nthreads) int omp_get_num_threads(void) int omp_get_max_threads(void) int omp_get_thread_num(void) int omp_get_num_procs(void) 88
Regiones paralelas Quién soy yo? Cuántos somos? Cada hilo paralelo se identifica por un número. El 0 es el hilo maestro. Dos funciones de la bibliotreca omp.h: tid = omp_get_thread_num(); devuelve el identificador del thread. nth = omp_get_num_threads(); devuelve el número de hilos generados. 89
Ejercicio Realizar un programa donde dentro de una región paralela se muestren los identificadores de los hilos y el número total de hilos. 90
Región crítica Una región o sección crítica es una secuencia de instrucciones que no debe ser interrumpida por otros proceso 91
Constructor critical float dot_prod(float* a, float* b, int N) { float sum = 0.0; #pragma omp parallel for for (int i=0; i<n; i++) { #pragma omp critical sum += a[i] * b[i]; } return sum; } // Sintaxis: #pragma omp critical [(lock_name)] Cuál será el problema aquí? 92
#include <omp.h> #include <stdio.h> #include <stdlib.h> Ejercicio- paralelizar } max = a[0]; #define SIZE 10 int main() { int i; int max; int a[size]; for (i = 0; i < SIZE; i++) { a[i] = rand(); printf("%d\n", a[i]); for (i = 1; i < SIZE; i++) { if (a[i] > max) { max = a[i]; } } } printf("max = %d\n", max); 93
Asignando Iteraciones La cláusula schedule permite dividir las iteraciones de los ciclos entre los hilos, indica como las iteraciones se asignan a los hilos. 94
Clausula schedule schedule(static,[chunk]) Bloques de iteraciones de tamaño chunk a los hilos Distribución Round robin schedule (dynamic,[chunk]) Los hilos toman un numero chunk de iteraciones, cuando estan sin trabajo. schedule(guided,[chunck]) Cada thread toma iteraciones dinámicamente y progresivamente va tomando menos iteraciones. 95
96
Ejemplo #pragma omp parallel for schedule (static, 8) for( int i = start; i <= end; i += 2 ) { if ( TestForPrime(i) ) gprimesfound++; } 97
Referencias Introduction to parallel programming, Intel Software College, junio 2007 Multicore programming practices guide, The Multicore Association www.openmp.org R. Chandra.Parallel Programming in OpenMP,Morgan Kaufmann, 2001. B. Chapman,Using OpenMP, The MIT Press, 2008. 98
Programación Paralela en OpenMp Parte 2 Proyecto PAPIME PE104911 Facultad de Ingeniería UNAM 99
Clausula reduction Las operaciones de reducción son comunes en muchas aplicaciones paralelas. Utilizan variables a las que acceden todos los procesos/hilos y sobre las que se efectúa alguna operación de acumulación en modo atómico. 100
Cláusula reduction #pragma omp reduction(operator:variable) #pragma omp parallel private(x) reduction(+:sum) { } X = sum = sum + X; La operador de reducción a utilizar. OJO: no se sabe en qué orden se va a ejecutar la operación --> debe ser conmutativa (cuidado con el redondeo). 101
Operaciones utilizados en reducciones (C/C++) Operator Initial Value Operator Initial Value + 0 & 0 * 1 0-0 && 1 ^ 0 0 102
Actividad Realizar un programa que realice el producto punto de dos vectores de dimensión n. Paralelizar el programa. 103
Cálculo del número Pi π= 0 1 4/(1+x2 ) dx La Regla de rectángulo consiste de estimar el área debajo de la curva y=4/(1+x2) entre x=0 y x=1 mediante áreas de rectángulos 104
Código Serial #include <stdio.h> #include <time.h> long long num_steps = 1000000000; double step; int main(int argc, char* argv[]) { clock_t start, stop; double x, pi, sum=0.0; int i; start = clock(); } x = (i +.5)*step; sum = sum + 4.0/(1.+ x*x); pi = sum*step; stop = clock(); printf( El valor de Pi es %15.12f\n",pi); printf( El tiempo para calcular PI fue %f segundos\n",((double)(stop - start)/1000.0)); { for (i=0; i<num_steps; i++) } return 0; 105
Para medir tiempo en OpenMP double empezar,terminar; empezar=omp_get_wtime( ); código terminar=omp_get_wtime(); printf( TIEMPO=%lf\n,empezar-terminar) El resultado es en segundos. 106
Una Solución #include <omp.h> static long num_steps = 100000; double step; #define NUM_THREADS 2 void main () { int i; double x, pi, sum[num_threads]; step = 1.0/(double) num_steps; omp_set_num_threads(num _THREADS) Elba Karen Sáenz García-} Oscar René Valdez #pragma omp parallel { double x; int id; id = omp_get_thread_num(); sum[id] = 0; #pragma omp for for (i=id;i< num_steps; i++){ x = (i+0.5)*step; sum[id] += 4.0/(1.0+x*x); } } for(i=0, pi=0.0;i<num_threads;i++) pi += sum[i] * step; 107
Otra Solución #include <omp.h> static long num_steps = 100000; double step; #define NUM_THREADS 2 void main () { int i; double x, pi, sum = 0.0; step = 1.0/(double) num_steps; omp_set_num_threads(num_threads); #pragma omp parallel for reduction(+:sum) private(x) for (i=1;i<= num_steps; i++){ x = (i-0.5)*step; sum = sum + 4.0/(1.0+x*x); } pi = step * sum; } 108
Clausula firstprivate Las variables privadas no se inicializan y al terminar la región paralela tienen un valor indefinido. Para inicializar una variable privada se utiliza firstprivate. 109
Ejemplo X = Y = Z = 0; #pragma omp parallel private(y) firstprivate(z) {... X = Y = Z = 1; }... valores dentro de la región paralela? X = 0 Y =? Z = 0 valores fuera de la región paralela? X = 1 Y =? (0) Z =? (0) 110
Cómo 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]); sol[i] = x[1] x[3];} Se pueden dividir las itereciones del ciclo exterior si j y x son privadas. Sin embargo, x[0] se necesita en la primera iteración del bucle interior. 111
Una solución 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]); sol[i] = x[1] x[3];} 112
Descomposicion Funcional v = alpha(); w = beta(); x = gamma(v, w); y = delta(); printf ("%6.2f\n", epsilon(x,y)); alpha beta gamma delta epsilon 113
Cómo se paraleliza? alpha beta gamma delta epsilon 114
Paralelismo funcional Secciones Paralelas Secciones independientes de código, se pueden ejecutar de forma concurrente #pragma omp parallel sections { #pragma omp section phase1(); #pragma omp section phase2(); #pragma omp section phase3(); } Serial Parallel 115
Rep. de tareas: funciones Constructor section Permite usar paralelismo de funcional (descomposición funcional). Reparte secciones de código independiente a hilos diferentes. Cada sección paralela es ejecutada por un sólo hilo, y cada hilo ejecuta ninguna o alguna sección. Una barrera implícita sincroniza el final de las secciones o 116
Posible solución #pragma omp parallel sections { #pragma omp section /* Opcional */ v = alpha(); #pragma omp section w = beta(); #pragma omp section y = delta(); } x = gamma(v, w); printf ("%6.2f\n", epsilon(x,y)); } 117
Otra Posibilidad alpha gamma beta delta Ejecutar alpha y beta en paralelo. Ejecutar gama y delta en paralelo. epsilon 118
Otra posibilidad #pragma omp parallel sections { #pragma omp section v=alpha(); #pragama omp section w=beta(); } #pragma omp parallel sections { #pragma omp section y=delta(); #pragma omp section x=gamma(v,w); } printf( %6.2f\n,epsilon(x,y); 119
Con dos secciones #pragma omp parallel { #pragma omp sections { #pragma omp section v = alpha(); #pragma omp section w = beta(); } #pragma omp sections { #pragma omp section x = gamma(v, w); #pragma omp section y = delta(); } } printf ("%6.2f\n", epsilon(x,y)); 120
Ejemplo de secciones #pragma omp parallel sections { #pragma omp section for(i=0;i<n;i++) c[i]=a[i]+b[i]; #pragma omp section for(j=0;j<n;j++) d[j]=e[j]+f[j]; } 121
Una posibilidad mejor #pragma omp parallel { #pragma omp for for(i=0;i<n;i++) c[i]=a[i]+b[i]; #pragma omp for for(j=0;j<n;j++) d[j]=e[j]+f[j]; } 122
o simplemente #pragma parallel for for(i=0;i<n;i++) { c[i]=a[i]+b[i]; d[i]=e[i]+f[i]; } 123
Barreras Implícitas Algunos constructores tiene barreras implícitas Parallel For Single Barreras no necesarias perjudican el desempeño 124
Ejercicio Paralelizar los dos códigos proporcionados, utilizando los constructores y clausulas vistos. 125
Referencias www.openmp.org OpenMP 2.5 Specifications Rohit Chandra, Parallel Programming in OpenMP. Morgan Kaufmann Publishers. Comunidad The community of OpenMP researchers and developers in academia and industry http://www.compunity.org/ Articulos conferencias: WOMPAT, EWOMP, WOMPEI, IWOMP http://www.nic.uoregon.edu/iwomp2005/index.html#program 126
Programación Paralela en OpenMp Parte 3 Proyecto PAPIME PE104911 Facultad de Ingeniería UNAM 127
Constructor Barrier Barrera Explicita Cada hilo espera hasta que todos lleguen a la barrera #pragma omp parallel shared (A, B, C) { DoSomeWork(A,B); printf( Processed A into B\n ); #pragma omp barrier DoSomeWork(B,C); printf( Processed B into C\n ); } 128
Constructor single Define un bloque básico de código, dentro de una región paralela, que debe ser ejecutado por un único hilo. Ejemplo, una operación de entrada/salida. No se especifica qué hilo ejecutará la tarea. 129
Constructor single #pragma omp single #pragma omp parallel { DoManyThings(); #pragma omp single { ExchangeBoundaries(); } // Hilos esperan } DoManyMoreThings(); 130
#pragma omp parallel {... ; #pragma omp single inicializar(a); #pragma omp for for(i=0; i<n; i++) A[i] = A[i] * A[i] + 1; parallel for single... ; } #pragma omp single copiar(b,a); single 131
Constructor maestro #pragma omp master { } #pragma omp parallel { DoManyThings(); #pragma omp master { // si no es el maestro,salta ExchangeBoundaries(); } DoManyMoreThings(); } 132
#include <omp.h> #include <stdio.h> int main( ) { int a[5], i; #pragma omp parallel { #pragma omp for for (i = 0; i < 5; i++) a[i] = i * i; #pragma omp master for (i = 0; i < 5; i++) printf_s("a[%d] = %d\n", i, a[i]); #pragma omp barrier #pragma omp for for (i = 0; i < 5; i++) a[i] += i; } } 133
Barreras Implícitas Algunos constructores tiene barreras implícitas Parallel For Single Barreras no necesarias perjudican el desempeño 134
Clausula nowait Permite ignorar barreras implicitas #pragma omp for nowait for(...) {...}; #pragma single nowait { [...] } #pragma omp for schedule(dynamic,1) nowait for(int i=0; i<n; i++) a[i] = bigfunc1(i); #pragma omp for schedule(dynamic,1) for(int j=0; j<m; j++) b[j] = bigfunc2(j); 135
Constructor atomic Asegura que una posición específica de memoria debe ser modificada de forma atómica, sin permitir que múltiples hilos intenten escribir en ella de forma simultánea. (sección critica). La sentencia debe tener una de las siguientes formas: x <operacion-binaria> = <expr> x++ ++x x--- ---x 136
Ejemplo atomic #include <stdio.h> #include <omp.h> #define MAX 10 int main() { int count = 0; #pragma omp parallel num_threads(max) { #pragma omp atomic count++; } printf("number of threads: %d\n", count); } 137
Paralelismo anidado Por defecto no es posible anidar regiones paralelas, hay que indicarlo explícitamente mediante: una llamada a una función omp_set_nested(true); una variable de entorno > export OMP_NESTED=TRUE Una función devuelve el estado de dicha opción: omp_get_nested(); (true o false) 138
Paralelismo anidado Master Región paralela externa Región paralela anidada Región paralela externa 139
Paralelismo anidado OpenMP 3.0 mejora el soporte al paralelismo anidado: -La función omp_set_num_threads() puede ser invocada dentro de una región paralela para controlar el grado del siguiente nivel de paralelismo. Permite conocer el nivel de anidamiento mediante omp_get_level() y omp_get_active_level(). Se puede tener acceso al identificador del padre de nivel n omp_get_ancestor_thread_num(n)y al número de threads en dicho nivel. 140
#include <omp.h> #include <stdio.h> Paralelismo anidado void report_num_threads(int level) { #pragma omp single { printf("level %d: number of threads in the team - %d\n", level, omp_get_num_threads()); } } 141
int main() { omp_set_dynamic(0); #pragma omp parallel num_threads(2) { report_num_threads(1); #pragma omp parallel num_threads(2) { report_num_threads(2); #pragma omp parallel num_threads(2) { report_num_threads(3); } } } return(0); } 142
Variable de ambiente SUNW_MP_MAX_POOL_THREADS Máximo numero de hilos esclavos en una región paralela Valor por defecto 1023 143
Referencias R. Chandra et al,parallel Programming in OpenMP,Morgan Kaufmann, 2001. B. Chapman et al Using OpenMP, The MIT Press, 2008. www.openmp.org Introduction to parallel programming, Intel Software College, junio 2007 144