Programación con OpenMP

50
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

Transcript of Programación con OpenMP

Page 1: 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

Page 2: Programación con OpenMP

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

Page 3: Programación con OpenMP

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

Page 4: Programación con OpenMP

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

Page 5: Programación con OpenMP

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)

Page 6: Programación con OpenMP

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

Page 7: Programación con OpenMP

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

Page 8: Programación con OpenMP

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]…]

Page 9: Programación con OpenMP

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 }

Page 10: Programación con OpenMP

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

Page 11: Programación con OpenMP

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) } }

Page 12: Programación con OpenMP

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); }

Page 13: Programación con OpenMP

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]

Page 14: Programación con OpenMP

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(); }

Page 15: Programación con OpenMP

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

Page 16: Programación con OpenMP

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

Page 17: Programación con OpenMP

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,…)

Page 18: Programación con OpenMP

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; } }

Page 19: Programación con OpenMP

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; }

Page 20: Programación con OpenMP

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; }

Page 21: Programación con OpenMP

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)

Page 22: Programación con OpenMP

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

Page 23: Programación con OpenMP

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]; }

Page 24: Programación con OpenMP

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

Page 25: Programación con OpenMP

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

Page 26: Programación con OpenMP

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?

Page 27: Programación con OpenMP

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

Page 28: Programación con OpenMP

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”

Page 29: Programación con OpenMP

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

Page 30: Programación con OpenMP

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}

Page 31: Programación con OpenMP

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();

}

Page 32: Programación con OpenMP

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(); }

Page 33: Programación con OpenMP

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(); }

Page 34: Programación con OpenMP

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.

Page 35: Programación con OpenMP

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);

Page 36: Programación con OpenMP

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”);

}

Page 37: Programación con OpenMP

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); }

Page 38: Programación con OpenMP

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>

Page 39: Programación con OpenMP

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…)

Page 40: Programación con OpenMP

Conceptos avanzados

Page 41: Programación con OpenMP

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

Page 42: Programación con OpenMP

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;

}

Page 43: Programación con OpenMP

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; }

Page 44: Programación con OpenMP

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

Page 45: Programación con OpenMP

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

Page 46: Programación con OpenMP

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

Page 47: Programación con OpenMP

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

Page 48: Programación con OpenMP

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.

Page 49: Programación con 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];}

}

Page 50: Programación con OpenMP

Programaciòn con OpenM Robinson Rivas-Suarez. SC-Camp 2011

50

¿Preguntas?

Material tomado de la Intel Software College