OpenMP : une API pour écrire des applications portables pour des machines à mémoire partagée
Programación con OpenMP
Transcript of Programación con OpenMP
Programación con OpenMP
Prof. Robinson Rivas-Suarez
Universidad Central de Venezuela Material tomado de la Intel Software College
SC-Camp 2011
Turrialba, Costa Rica, julio 11~15
Programaciòn con OpenM Robinson Rivas-Suarez. SC-Camp 2011
2
Objetivos
Al término de este módulo el estudiante será capaz de
• Crear hilos utilizando pragmas OpenMP
• Usar pragmas de sincronización OpenMP para coordinar la ejecución de los hilos y acceso a memoria
Programaciòn con OpenM Robinson Rivas-Suarez. SC-Camp 2011
3
Agenda
¿Qué es OpenMP?
Regiones Paralelas
Bloques de construcción para trabajo en paralelo
Alcance de los datos para proteger datos
Sincronización Explícita
Cláusulas de Planificación
Otros bloques de construcción y cláusulas útiles
Programaciòn con OpenM Robinson Rivas-Suarez. SC-Camp 2011
4
¿Qué es OpenMP*?
Directivas del compilador para programación multihilos
Es fácil crear hilos en Fortran y C/C++
Soporta el modelo de paralelismo de datos
Paralelismo incremental
Combina código serial y paralelo en un solo código fuente
Programaciòn con OpenM Robinson Rivas-Suarez. SC-Camp 2011
5
¿Qué es OpenMP*?
omp_set_lock(lck)
#pragma omp parallel for private(A, B)
#pragma omp critical
C$OMP parallel do shared(a, b, c)
C$OMP PARALLEL REDUCTION (+: A, B)
call OMP_INIT_LOCK (ilok)
call omp_test_lock(jlok)
setenv OMP_SCHEDULE “dynamic”
CALL OMP_SET_NUM_THREADS(10)
C$OMP DO lastprivate(XX)
C$OMP ORDERED
C$OMP SINGLE PRIVATE(X)
C$OMP SECTIONS
C$OMP MASTER
C$OMP ATOMIC
C$OMP FLUSH
C$OMP PARALLEL DO ORDERED PRIVATE (A, B, C)
C$OMP THREADPRIVATE(/ABC/)
C$OMP PARALLEL COPYIN(/blk/)
Nthrds = OMP_GET_NUM_PROCS()
!$OMP BARRIER
http://www.openmp.org La especificación actual es OpenMP 2.5
250 Páginas
(C/C++ y Fortran)
Programaciòn con OpenM Robinson Rivas-Suarez. SC-Camp 2011
6
Arquitectura OpenMP*
Modelo fork-join
Bloques de construcción para trabajo en paralelo
Bloques de construcción para el ambiente de datos
Bloques de construcción para sincronización
API (Application Program Interface) extensiva para afinar el control
Programaciòn con OpenM Robinson Rivas-Suarez. SC-Camp 2011
7
Modelo de programación
Paralelismo fork-join: • El hilo maestro se divide en un equipo de hilos como sea
necesario
• El Paralelismo se añade incrementalmente: el programa secuencial se convierte en un programa paralelo
Regiones paralelas
Hilo maestro
Programaciòn con OpenM Robinson Rivas-Suarez. SC-Camp 2011
8
Sintaxis del Pragma OpenMP*
La mayoría de los bloques de construcción en OpenMP* son directivas de compilación o pragmas.
• En C y C++, los pragmas toman la siguiente forma:
#pragma omp construct [clause [clause]…]
Programaciòn con OpenM Robinson Rivas-Suarez. SC-Camp 2011
9
Regiones Paralelas
Define una región paralela sobre un bloque de código estructurado
Los hilos se crean como ‘parallel’
Los hilos se bloquean al final de la región
Los datos se comparten entre hilos al menos que se especifique otra cosa
#pragma omp parallel
Hilo
1 Hilo
2 Hilo
3
C/C++ : #pragma omp parallel
{ bloque }
Programaciòn con OpenM Robinson Rivas-Suarez. SC-Camp 2011
10
¿Cuántos hilos?
Establecer una variable de ambiente para el número de hilos
set OMP_NUM_THREADS=4
No hay un default estándar en esta variable
• En muchos sistemas: • # de hilos = # de procesadores • Los compiladores de Intel® usan este default
Programaciòn con OpenM Robinson Rivas-Suarez. SC-Camp 2011
11
Actividad 1: Hello Worlds
Modificar el código serial de “Hello, Worlds” para ejecutarse paralelamente usando OpenMP*
int main() { saludo(); } int saludo() { int i;
for(i=0;i<10;i++) { printf(“Hola mundo desde el hilo principal\n”); sleep(1) } }
Programaciòn con OpenM Robinson Rivas-Suarez. SC-Camp 2011
12
Bloques de construcción de trabajo en paralelo
Divide las iteraciones del ciclo en hilos
Debe estar en la región paralela
Debe preceder el ciclo
#pragma omp parallel #pragma omp for
for (i=0; i<N; i++){ Do_Work(i); }
Programaciòn con OpenM Robinson Rivas-Suarez. SC-Camp 2011
13
Bloques de construcción de trabajo en paralelo
Los hilos se asignan a un conjunto de iteraciones independientes
Los hilos deben de esperar al final del bloque de construcción de trabajo en paralelo
#pragma omp parallel
#pragma omp for
Barrera implícita
i = 0
i = 1
i = 2
i = 3
i = 4
i = 5
i = 6
i = 7
i = 8
i = 9
i = 10
i = 11
#pragma omp parallel #pragma omp for for(i = 0; i < 12; i++) c[i] = a[i] + b[i]
Programaciòn con OpenM Robinson Rivas-Suarez. SC-Camp 2011
14
Combinando pragmas
Ambos 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(); }
Programaciòn con OpenM Robinson Rivas-Suarez. SC-Camp 2011
15
Ambiente de datos
OpenMP usa un modelo de programación de memoria compartida
• La mayoría de las variables por default son compartidas.
• Las variables globales son compartidas entre hilo
Programaciòn con OpenM Robinson Rivas-Suarez. SC-Camp 2011
16
Ambiente de datos
Pero, no todo es compartido... • Las variables en el stack en funciones llamadas de regiones
paralelas son PRIVADAS
• Las variables automáticas dentro de un bloque son PRIVADAS
• Las variables de índices en ciclos son privadas (salvo excepciones) • C/C+: La primera variable índice en el ciclo en ciclos anidados
después de un #pragma omp for
Programaciòn con OpenM Robinson Rivas-Suarez. SC-Camp 2011
17
Atributos del alcance de datos
El estatus por default puede modificarse
default (shared | none)
Clausulas del atributo de alcance
shared(varname,…)
private(varname,…)
Programaciòn con OpenM Robinson Rivas-Suarez. SC-Camp 2011
18
La cláusula Private
Reproduce la variable por cada hilo • Las variables no son inicializadas; en C++ el objeto es construido
por default • Cualquier valor externo a la región paralela es indefinido
void* work(float* c, int N) { float x, y; int i; #pragma omp parallel for private(x,y) for(i=0; i<N; i++) {
x = a[i]; y = b[i]; c[i] = x + y; } }
Programaciòn con OpenM Robinson Rivas-Suarez. SC-Camp 2011
19
Ejemplo: producto punto
float dot_prod(float* a, float* b, int N) { float sum = 0.0; #pragma omp parallel for shared(sum) for(int i=0; i<N; i++) { sum += a[i] * b[i]; } return sum; }
Programaciòn con OpenM Robinson Rivas-Suarez. SC-Camp 2011
20
Proteger datos compartidos
Debe proteger el acceso a los datos compartidos que son modificables
float dot_prod(float* a, float* b, int N) { float sum = 0.0; #pragma omp parallel for shared(sum) for(int i=0; i<N; i++) { #pragma omp critical sum += a[i] * b[i]; } return sum; }
Programaciòn con OpenM Robinson Rivas-Suarez. SC-Camp 2011
21
#pragma omp critical [(lock_name)]
Define una región crítica en un bloque estructurado
OpenMP* Bloques de construcción para regiones críticas
float R1, R2; #pragma omp parallel { float A, B; #pragma omp for for(int i=0; i<niters; i++){ B = big_job(i); #pragma omp critical consum (B, &R1); A = bigger_job(i); #pragma omp critical consum (A, &R2); } }
Los hilos esperan su turno –en un momento, solo uno llama consum() protegiendo R1 y R2 de de condiciones de concurso.
Nombrar las regiones críticas es opcional, pero puede mejorar el rendimiento.
(R1_lock)
(R2_lock)
Programaciòn con OpenM Robinson Rivas-Suarez. SC-Camp 2011
22
OpenMP* Cláusula de reducción
reduction (op : list)
Las variables en “list” deben ser compartidas dentro de la región paralela
Adentro de parallel o el bloque de construcción de trabajo en paralelo:
• Se crea una copia PRIVADA de cada variable de la lista y se inicializa de acuerdo al “op”
• Estas copias son actualizadas localmente por los hilos
• Al final del bloque de construcción, las copias locales se combinan de acuerdo al “op” a un solo valor y se almacena en la variable COMPARTIDA original
Programaciòn con OpenM Robinson Rivas-Suarez. SC-Camp 2011
23
Ejemplo de reducción
Una copia local de sum para cada hilo
Todas las copias locales de sum se suman y se almacenan en una variable “global”
#pragma omp parallel for reduction(+:sum) for(i=0; i<N; i++) { sum += a[i] * b[i]; }
Programaciòn con OpenM Robinson Rivas-Suarez. SC-Camp 2011
24
Un rango de operadores asociativos y conmutativos pueden usarse con la reducción
Los valores iniciales son aquellos que tienen sentido
C/C++ Operaciones de reducción
Operador Valor Inicial
+ 0
* 1
- 0
^ 0
Operador Valor Inicial
& ~0
| 0
&& 1
|| 0
Programaciòn con OpenM Robinson Rivas-Suarez. SC-Camp 2011
25
Ejemplo de integración numérica
4.0
2.0
1.0 0.0
4.0 (1+x2)
f(x) = ∫ 4.0 (1+x2) dx = π
0
1
X
Programaciòn con OpenM Robinson Rivas-Suarez. SC-Camp 2011
26
Actividad 2 - Calculando Pi
Paraleliza el código de integración numérica usando OpenMP
¿Qué variables se pueden compartir?
¿Qué variables deben ser privadas?
¿Qué variables deberían considerarse para reducción?
Programaciòn con OpenM Robinson Rivas-Suarez. SC-Camp 2011
27
Asignando Iteraciones
La cláusula schedule afecta en como las iteraciones del ciclo se mapean a los hilos
schedule(static [,chunk]) • Bloques de iteraciones de tamaño “chunk” a los hilos • Distribución Round Robin
schedule(dynamic[,chunk]) • Los hilos timan un fragmento (chunk) de iteraciones • Cuando terminan las iteraciones, el hilo solicita el siguiente
fragmento
Programaciòn con OpenM Robinson Rivas-Suarez. SC-Camp 2011
28
Asignando Iteraciones
schedule(guided[,chunk]) • Planificación dinámica comenzando desde el bloque más
grande • El tamaño de los bloques se compacta; pero nunca m ás
pequeño que “chunk”
Programaciòn con OpenM Robinson Rivas-Suarez. SC-Camp 2011
29
Cláusula Schedule Cuando utilizar
STATIC Predecible y trabajo similar por iteración
DYNAMIC Impredecible, trabajo altamente variable por iteración
GUIDED Caso especial de dinámico para reducir la sobrecarga de planificación
Qué planificación utilizar
Programaciòn con OpenM Robinson Rivas-Suarez. SC-Camp 2011
30
Ejemplo de la cláusula Schedule
#pragma omp parallel for schedule (static, 8) for( int i = start; i <= end; i += 2 ) { if ( TestForPrime(i) ) gPrimesFound++; }
Las iteraciones se dividen en pedazos de 8 • Si start = 3, el primer pedazo es i={3,5,7,9,11,13,15,17}
Programaciòn con OpenM Robinson Rivas-Suarez. SC-Camp 2011
31
Secciones paralelas
Secciones independientes de código se pueden ejecutar concurrentemente
Serial Paralela
#pragma omp parallel sections
{
#pragma omp section
phase1();
#pragma omp section
phase2();
#pragma omp section
phase3();
}
Programaciòn con OpenM Robinson Rivas-Suarez. SC-Camp 2011
32
Denota un bloque de código que será ejecutado por un solo hilo
• El hilo seleccionado es dependiente de la implementación
Barrera implícita al final
Bloque de construcción Single
#pragma omp parallel { DoManyThings(); #pragma omp single { ExchangeBoundaries(); } // threads wait here for single DoManyMoreThings(); }
Programaciòn con OpenM Robinson Rivas-Suarez. SC-Camp 2011
33
Denota bloques de código que serán ejecutados solo por el hilo maestro
No hay barrera implícita al final
Bloque de construcción Master
#pragma omp parallel { DoManyThings(); #pragma omp master { // if not master skip to next stmt ExchangeBoundaries(); } DoManyMoreThings(); }
Programaciòn con OpenM Robinson Rivas-Suarez. SC-Camp 2011
34
Barreras implícitas
Varios bloques de construcción de OpenMP* tienen barreras implícitas • parallel • for • single
Barreras innecesarias deterioran el rendimiento • Esperar hilos implica que no se trabaja!
Suprime barreras implícitas cuando sea seguro con la cláusula nowait.
Programaciòn con OpenM Robinson Rivas-Suarez. SC-Camp 2011
35
Cláusula Nowait
Cuando los hilos esperarían entren cómputos independientes
#pragma single nowait
{ [...] }
#pragma omp for nowait
for(...) {...};
#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);
Programaciòn con OpenM Robinson Rivas-Suarez. SC-Camp 2011
36
Barreras
Sincronización explícita de barreras
Cada hilo espera hasta que todos lleguen
#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”);
}
Programaciòn con OpenM Robinson Rivas-Suarez. SC-Camp 2011
37
Operaciones Atómicas
Caso especial de una sección crítica
Aplica solo para la actualización de una posición de memoria
#pragma omp parallel for shared(x, y, index, n) for (i = 0; i < n; i++) { #pragma omp atomic x[index[i]] += work1(i); y[i] += work2(i); }
Programaciòn con OpenM Robinson Rivas-Suarez. SC-Camp 2011
38
API de OpenMP*
Obtener el número de hilo dentro de un equipo
int omp_get_thread_num(void);
Obtener el número de hilos en un equipo
int omp_get_num_threads(void);
Usualmente no se requiere para códigos de OpenMP • Tiene usos específicos (debugging) • Hay que incluir archivo de cabecera
#include <omp.h>
Programaciòn con OpenM Robinson Rivas-Suarez. SC-Camp 2011
39
Programación con OpenMP ¿Qué se cubrió?
OpenMP* es: • Una aproximación simple a la programación paralela para
computadoras con memoria compartida
Exploramos OpenMP para saber como: • Hacer regiones de código en paralelo (omp parallel) • Dividir el trabajo (omp for) • Categorizar variables (omp private….) • Sincronización (omp critical…)
Conceptos avanzados
Programaciòn con OpenM Robinson Rivas-Suarez. SC-Camp 2011
41
Mas sobre OpenMP*
Bloques de construcción para el ambiente de datos • FIRSTPRIVATE • LASTPRIVATE • THREADPRIVATE
Programaciòn con OpenM Robinson Rivas-Suarez. SC-Camp 2011
42
Variables inicializadas de una variable compartida
Los objetos de C++ se construyen a partir de una copia
Cláusula Firstprivate
incr=0; #pragma omp parallel for firstprivate(incr) for (I=0;I<=MAX;I++) {
if ((I%2)==0) incr++; A(I)=incr;
}
Programaciòn con OpenM Robinson Rivas-Suarez. SC-Camp 2011
43
Cláusula Lastprivate
Las variables actualizan la variable compartida usando el valor de la última iteración
Los objetos de C++ se actualizan por asignación
void sq2(int n, double *lastterm)
{ double x; int i; #pragma omp parallel #pragma omp for lastprivate(x) for (i = 0; i < n; i++){ x = a[i]*a[i] + b[i]*b[i]; b[i] = sqrt(x); } lastterm = x; }
Programaciòn con OpenM Robinson Rivas-Suarez. SC-Camp 2011
44
Preserva el alcance global en el almacenamiento por hilo
Usa copia para inicializar a partir del hilo maestro
Cláusula Threadprivate
struct Astruct A; #pragma omp threadprivate(A) …
#pragma omp parallel copyin(A) do_something_to(&A); …
#pragma omp parallel do_something_else_to(&A);
Las copias privadas de “A” persisten entre regiones
Programaciòn con OpenM Robinson Rivas-Suarez. SC-Camp 2011
45
Problemas de rendimiento
Los hilos ociosos no hacen trabajo útil
Divide el trabajo entre hilos lo más equitativamente posible • Los hilos deben terminar trabajos paralelos al mismo tiempo
La sincronización puede ser necesaria • Minimiza el tiempo de espera de recursos protegidos
Programaciòn con OpenM Robinson Rivas-Suarez. SC-Camp 2011
46
Cargas de trabajo no balanceadas
Cargas de trabajo desigual produce hilos ociosos y desperdicio de tiempo.
time
Ocupado Ocioso
#pragma omp parallel {
#pragma omp for for( ; ; ){
}
}
tiempo
Programaciòn con OpenM Robinson Rivas-Suarez. SC-Camp 2011
47
#pragma omp parallel {
#pragma omp critical { ... } ... }
Sincronización
Tiempo perdido por locks
tiempo
Ocupado Ocioso En SC
Programaciòn con OpenM Robinson Rivas-Suarez. SC-Camp 2011
48
Afinando el rendimiento
Los profilers usan muestreo para proveer datos sobre el rendimiento.
Los profilers tradicionales están limitados para usarse con códigos de OpenMP*:
• Miden tiempo del CPU, no tiempo real • No reportan contención de objetos de sincronización • No pueden reportar carga de trabajo desbalanceada • Muchos de ellos no tienen todo el soporte de OpenMP
Los programadores necesitan profilers específicamente diseñadas para OpenMP.
Programaciòn con OpenM Robinson Rivas-Suarez. SC-Camp 2011
49
Planificación estática: Hacerlo por uno mismo
Debe conocerte: • Número de hilos (Nthrds) • Cada identificador ID de cada hilo (id)
Calcular iteraciones (start y end):
#pragma omp parallel {
int i, istart, iend; istart = id * N / Nthrds; iend = (id+1) * N / Nthrds; for(i=istart;i<iend;i++){ c[i] = a[i] + b[i];}
}
Programaciòn con OpenM Robinson Rivas-Suarez. SC-Camp 2011
50
¿Preguntas?
Material tomado de la Intel Software College