Introducción a Introducción a OpenMPOpenMP · OpenMP se basa en directivas al compilador (¡el...
Transcript of Introducción a Introducción a OpenMPOpenMP · OpenMP se basa en directivas al compilador (¡el...
Arquitectura de ComputadoresArquitectura de Computadores::Arquitectura de ComputadoresArquitectura de Computadores::
Práctica de MultiprocesadoresPráctica de Multiprocesadores
Introducción a Introducción a OpenMPOpenMP
ÍndiceÍndice
1 Introducción1. Introducción 2. Regiones Paralelas: 3. Distribución del trabajo4. Gestión de datos5. Sincronización6 F i d bibli t6. Funciones de biblioteca7. Variables del entorno8. Ejemplo Π
AC : MP: Introd. a OpenMP 2
¿Qué es OpenMP?¿Qué es OpenMP?API estándar “de facto” para la programación multithread desistemas de memoria compartida (C, C++ y Fortran)
Consta de:
● Directivas para el compilador● Directivas para el compilador● Funciones de librería● Variables de entorno● Variables de entorno
AC : MP: Introd. a OpenMP 3
IntroducciónIntroducción OpenMP se basa en directivas al compilador (¡el código es
compilable incluso si el compilador no soporta OpenMP!)p p p p )
Que se aplican a “bloques estructurados”: una o más sentencias con un punto de entrada y uno de salidap y
Se apoya en threads, para la paralelización (modelo SPMD)
O MP b l l li ió d b l (d ) OpenMP se basa en la paralelización de bucles (datos)
Mismo código fuente para secuencial y paraleloSe protege con el preprocesador: #ifdef _OPENMP ….
Los prototipos de funciones y los tipos están en el fichero:p p y p#include <omp.h>
¡Puede haber interbloqueos y carreras!
AC : MP: Introd. a OpenMP 4
¡ q y También soporta vectorización y coprocesadores
Modelo de programación de OpenMPModelo de programación de OpenMP
Modelo de paralelismo: Fork-Join El programa comienza con un solo thread (maestro) El maestro crea threads según necesidad
AC : MP: Introd. a OpenMP 5
EjemploEjemplo
// Secuencial:void main(){
// Paralelo:void main(){{
double Res[1000];{
double Res[1000];
for(int i=0;i<1000;i++)do huge comp(Res[i]);
#pragma omp parallel forfor(int i=0;i<1000;i++)
do huge comp(Res[i]);_ g _ p}
_ g _ p}
Similar la versión paralela y la secuencialSimilar la versión paralela y la secuencial. Pocos cambios, legible y fácil de mantener
ACAR: Introducción a OpenMP 6
Creación de threads: Regiones ParalelasCreación de threads: Regiones ParalelasSe declaran con la directiva
# ll l [ lá l ]#pragma omp parallel [cláusulas] {//código…}
Crea N threads que ejecutan en paralelo el mismo código, solo cambia su ID.
¡Al final de la región hay una barrera implícita!
El número de threads depende de variables internas p(num_threads, max_threads, dynamic)
o de la cláusula num threads(int)o de c usu u _t eads( t)
Si se pone la cláusula if, se paraleliza sólo si se cumple la condición:…parallel if(N>100)…
AC : MP: Introd. a OpenMP 7
condición:…parallel if(N>100)…
Regiones Paralelas: EjemploRegiones Paralelas: Ejemplo
#include “omp.h”#include omp.h…………
double A[1000];
Funciones de librería
double A[1000];omp_set_num_threads(4);#pragma omp parallel#pragma omp parallel{
int ID = omp get thread num();int ID = omp_get_thread_num();sumarElemA (ID,A);
}}
Cada thread llama a sumarElemA para ID=0 .. 3l i d A id d l h d
AC : MP: Introd. a OpenMP 8
Una sola copia de A, compartida por todos los threads
Regiones Paralelas: EjemploRegiones Paralelas: Ejemplo
#include “omp.h”#include omp.h…………
double A[1000]; cláusuladouble A[1000];
#pragma omp parallel num threads(4)#pragma omp parallel num_threads(4){
int ID = omp get thread num();int ID = omp_get_thread_num();sumarElemA (ID,A);
}}
Cada thread llama a sumarElemA para ID=0 .. 3l i d A id d l h d
AC : MP: Introd. a OpenMP 9
Una sola copia de A, compartida por todos los threads
Distribución del trabajo: forDistribución del trabajo: for
Se declara con la directiva#pragma omp for [cláusulas]for (;;) {//código…}for (;;) {//código…}
Divide las iteraciones de un bucle entre los threadsdi ibldisponibles.
Al final hay una barrera implícita,evitable con cláusula nowait
Se puede especificar cómo se reparten las iteraciones entre Se puede especificar cómo se reparten las iteraciones entre los threads:
cláusula schedule
AC : MP: Introd. a OpenMP 10
cláusula schedule
Distribución del trabajo for: EjemploDistribución del trabajo for: Ejemplo
1. Código secuencial for(i=0;i<N;i++) g
#pragma omp parallel{
{a[i] = a[i] + b[i];}
2. Región Paralela OpenMPdi ib ió d b j {
int id, i,Nthrds,istart,iend;id = omp_get_thread_num();Nthrds =omp get num threads();
distribución de trabajo manualmente(id, i, Nthrds, Nthrds omp_get_num_threads();
istart = id * N / Nthrds;iend = (id+1) * N / Nthrds;for(i=istart;i<iend;i++)
istart, iend: son variables privadas, ¿por qué? ¿deben serlo?)
3 R ió P l l O MP
( ){ a[i] = a[i] + b[i];}
}
¿p q ¿ )
#3. Región Paralela OpenMP y distribución de trabajo for
#pragma omp parallel#pragma omp for schedule(static)for(i=0;i<N;i++) { [i] [i] + b[i] }
AC : MP: Introd. a OpenMP 11
{ a[i] = a[i] + b[i];}
Distribución del trabajo for: PlanificaciónDistribución del trabajo for: PlanificaciónPlanificación con la cláusula schedule:
##pragma omp for schedule(..)
schedule (static [,chunk])Asigna bloques fijos de iteraciones de tamaño “chunk” a cada thread
schedule (dynamic [,chunk])C d h d “ h k” i i h i dCada thread coge “chunk” iteraciones hasta terminar con todas
schedule (guided [,chunk])C d th d di á i t bl d it i● Cada thread coge dinámicamente bloques de iteraciones
● El bloque inicialmente es grande (nº iteraciones sin asignar dividido por nº threads) y va bajando hasta tamaño“chunk”
schedule (runtime)Planificación y tamaño de bloque determinado por la variable de entorno OMP SCHEDULE
AC : MP: Introd. a OpenMP 12
entorno OMP_SCHEDULE
Planificación: Ejemploj p200 iteraciones en 4 threads
AC : MP: Introd. a OpenMP 13
Distribución del trabajo: sectionsDistribución del trabajo: sections
Asigna bloques de código a threadsAsigna bloques de código a threads.
Ejemplo:#pragma omp parallel#pragma omp sections{{x_calculation();
#pragma omp sectiony_calculation();
#pragma omp sectionz calculation();_ ();
}
Al final hay una barrera (evitable con nowait)
AC : MP: Introd. a OpenMP 14
Gestión de los datosGestión de los datos
Modelo de programación de memoria compartida:Modelo de programación de memoria compartida:● La mayoría de las variables son compartidas por defecto● Las variables globales son compartidasLas variables globales son compartidas
Pero no todas las variables son compartidas:Al d b ífi d h d● Algunas deben ser específicas para cada thread
● Las variables declaradas dentro de una región paralela
● Las ubicadas en cada pila propia (parámetros y variables locales) son privadas (cada thread tiene su pila)
Se puede cambiar los ‘atributos’ de las variables heredadas del maestro mediante cláusulas
AC : MP: Introd. a OpenMP 15
Gestión de los datosGestión de los datos
shared: Variable común a todos los threadsshared: Variable común a todos los threadsCuidado: puede ser necesario utilizar regiones críticas
i t C d h d ti “ ” i l l private: Cada thread tiene “su” copia local. Sin inicializar y valor indefinido tras la región paralela
firstprivate: Es “private”, pero se inicializa con el valor de la ‘original’ (variable del maestro)
lastprivate: Es “private”, pero al final se le asigna el valor que toma en la última iteración o sección
default: shared, private (FORTRAN) o none
AC : MP: Introd. a OpenMP 16
Gestión de los datosGestión de los datos threadprivate: hace una copia de una variable, privada
d h d i l l d l j ió (para cada thread. Existe a lo largo de la ejecución (en secuencial se ve la copia del maestro)
copyin: inicializa las variables threadprivate con el valor de la del maestro
copyprivate: pasa el valor dado por un thread al resto (se usa con single)
reduction (op:list): deben ser variables shared• Hará una copia local y la inicializará según “op”• Al final las copias locales se reducen a una global• Operadores: + * - & | ^ && || min max
AC : MP: Introd. a OpenMP 17
Gestión de los datos: Ejemplosj p1. int tmp=0;
#pragma omp parallel private(i) firstprivate(tmp)#pragma omp parallel private(i) firstprivate(tmp){ i = 3 + func(id);tmp = tmp + 2;}
2. #pragma omp parallel for lastprivate(i)for (i=0; i<n-1; i++)
a[i] = b[i] + b[i+1a[i]=b[i]; // caso n-1 fuera bucle
3. double ave=0.0, A[MAX], int i;#pragma omp parallel for \
h d l ( t ti ) d ti ( )schedule (static)reduction(+:ave)for (i=0; i<MAX; i++)
ave+= A[i];/MAX
AC : MP: Introd. a OpenMP 18
ave = ave/MAX
Gestión de los datosGestión de los datos1. int counter = 0; // Nº tareas ejecutadas por cada hilo…
#pragma omp threadprivate(counter)
2 #pragma omp threadprivate(work size)2. #pragma omp threadprivate(work,size)
#pragma omp parallel copyin(size) shared(N){
work = build(tol,size+N);}
3. #pragma omp parallel for reduction(+:res) lastprivate(Z,i)for (i=0; i< 1000; i++){
Z = func(I);Z = func(I);res = res + Z;
}
ACAR: Introducción a OpenMP 19
SincronizaciónSincronización
critical [name]: Definición de una región crítica.critical [name]: Definición de una región crítica.Los threads esperan al comienzo de la región crítica hasta que no
haya ningún hilo ejecutando una región crítica con el mismo b T d l ti b id tinombre. Todas las que no tienen nombre, se consideran que tienen
un mismo nombre no especificado
Atomic [read|write|update|capture]: Asegura una actualización atómica. Por defecto update
L t tó i● Lectura atómica: v = x;● Escritura atómica: x = expr; //expr no atómica● Actualización atómica: x = x binop expr;● Actualización atómica: x x binop expr;● “Captura” atómica: v = x binop= expr; // x atómico
AC : MP: Introd. a OpenMP 20
SincronizaciónSincronización
barrier: Implementa una barrerabarrier: Implementa una barrera
ordered: Asegura que las iteraciones se ejecutan en el mismo orden que en secuencial: ¡¡evítese en lo posible!!mismo orden que en secuencial: ¡¡evítese en lo posible!!
master: Sólo el maestro ejecuta dicho código, los demás se lo saltan. Sin barrera.
single: Un solo thread ejecuta dicho código, tiene una barrera g j g ,implícita. Con copyprivate puede hacer visible a los demás threads los cálculos hechos.
AC : MP: Introd. a OpenMP 21
Sincronización: EjemplosSincronización: Ejemplos1. #pragma omp parallel for schedule(dynamic) private(a)
for (i=0; i<N; i++){a = work(i); // en paralelo
#pragma omp ordered // espera que le toqueprintf(“%d\n", a); //impresión resultados ordenadaprintf( %d\n , a); //impresión resultados ordenada
}2. #pragma omp threadprivate(x, y)
void init(float a float b ) { // a y b privadosvoid init(float a, float b ) { // a y b privados#pragma omp single copyprivate(a,b,x,y)
scanf("%f %f %f %f", &a, &b, &x, &y); }}
3. #pragma omp critical qlockenqueue(job);
…#pragma omp critical qlock
dequeue(job);
AC : MP: Introd. a OpenMP 22
SincronizaciónSincronización
1. omp_lock_t *new_lock()_ _ _{omp_lock_t *lock_ptr;#pragma omp single copyprivate(lock_ptr){lock_ptr = (omp_lock_t *)malloc(sizeof(omp_lock_t));omp_init_lock( lock_ptr );//} //barrera, todos salen con el cerrojo!!!
return lock_ptr;}
AC : MP: Introd. a OpenMP 23
TareasTareas
A partir de OpenMP 3 0A partir de OpenMP 3.0
Permite definir una “task”: conjunto de código y datos j ta ejecutar:
#pragma omp task firstprivate(my_pointer)
(void) do independent work (my pointer);(void) do_independent_work (my_pointer);
Si hay algún thread disponible se pone a ejecutarla, si no espera uno libre.no espera uno libre.
Se espera por ellas en las barreras implícitas y explícitasexplícitas
2424ACAR: Introducción a OpenMP
OpenMP 4 0OpenMP 4.0 Está disponible OpenMP 4.0 (http://www.openmp.org) Dos cambios importantes: vectorización y coprocesadores Vectorización: nuevo #pragma omp simd para vectorizar
bucles. Toma la idea de Intel (icc). Con claúsulas● Busca aprovechar las unidades vectoriales: MMX, SSE, AVX,
MIC) Se podrá combinar con regiones paralelas:MIC). Se podrá combinar con regiones paralelas:#pragma omp parallel for simd
Coprocesadores: Se busca aprovechar las GPUs y MICs de Coprocesadores: Se busca aprovechar las GPUs y MICs, de gran potencia de cálculo. ● Se introduce #pragma omp target para indicar elSe introduce #pragma omp target para indicar el
dispositivo sobre el que se quiere ejecutar ● Toma la idea de PG, que ya dispone del OpenACC, un
ACAR: Introducción a OpenMP 25
OpenMP de pago para GPUs
Funciones de biblioteca: Entorno de Ejecución
Gestión de threadsGestión de threads• void omp_set_num_threads(int)• int omp get num threads(void)t o p_get_ u _t eads( o d)• int omp_get_thread_num(void)• int omp_get_max_threads(void)_ _ _• void omp_set_dynamic(bool)• bool omp_get_dynamic(void)
Anidamiento del paralelismo• void omp set nested(bool)void omp_set_nested(bool)• bool omp_get_nested(void)
AC : MP: Introd. a OpenMP 26
Funciones de biblioteca: Entorno de Ejecución y Cerrojos
CerrojosCerrojos• void omp_init_lock(lock)• void omp_destroy_lock(lock)• void omp_set_lock(lock)• void omp_unset_lock(lock)
oid omp test lock(lock)• void omp_test_lock(lock) ¿En una región paralela?
bool omp in parallel(void)bool omp_in_parallel(void)
Número procesadores:int omp num procs(void)int omp_num_procs(void)
Tomar tiemposomp get wtime(), omp get wtick()
AC : MP: Introd. a OpenMP 27
p_g _ p_g _
Variables del Entorno del EjecuciónVariables del Entorno del Ejecución
OMP SCHEDULE “schedule[, chunk size]”OMP_SCHEDULE schedule[, chunk_size]
OMP_NUM_THREADS int_literal // Máximo
b l // j l ú d OMP_DYNAMIC bool //Ajusta el número de hilos en cada región paralela
OMP_NESTED bool
OMP_PROC_BIND bool
OMP_STACKSIZE int [B|K|M|G}
OMP WAIT POLICY passive || activeOMP_WAIT_POLICY passive || active
OMP_THREAD_LIMIT int
AC : MP: Introd. a OpenMP 28
CompilaciónCompilación
Incluir el fichero de cabecera: #include <omp.h>p
Se activa _OPENMP
Compilador de GCC:gcc -fopenmpgfortran -fopenmp
Compilador de Intel:Compilador de Intel:icc -openmpifort –openmp
AC : MP: Introd. a OpenMP 29
Ejemplo del cálculo de PiEjemplo del cálculo de Pi Por cálculo númerico:
dx
x1
0 210.4
Se aproxima como:
x0 1
xxFN
i )(
con F(xi) el alto a mitad del
i 0
intervalo y x el ancho del intervalo
AC : MP: Introd. a OpenMP 30
Ejemplo del cálculo de Pi : SecuencialEjemplo del cálculo de Pi : Secuencial
static long num_steps = 100000;double step;void main (){void main (){
int i; double x, pi, sum = 0.0;step = 1.0/(double) num_steps;_for (i=0;i< num_steps; i++){
x = (i+0.5)*step;/sum = sum + 4.0/(1.0+x*x);
}pi = step * sum;pi = step sum;
}
AC : MP: Introd. a OpenMP 31