Sei sulla pagina 1di 31

Arquitectura de Computadores:

Prctica de Multiprocesadores
Introduccin a OpenMP
ndice
1 Introduccin
1.
2. Regiones Paralelas:
3. Distribucin del trabajo
4. Gestin de datos
5. Sincronizacin
6 Funciones
6. F i de
d bibli
biblioteca
t
7. Variables del entorno
8. Ejemplo

AC : MP: Introd. a OpenMP 2


Qu es OpenMP?
API estndar de facto para la programacin multithread de
sistemas de memoria compartida (C, C++ y Fortran)

Consta de:
Directivas para el compilador
Funciones de librera
Variables de entorno

AC : MP: Introd. a OpenMP 3


Introduccin
OpenMP se basa en directivas al compilador (el cdigo es
compilable
p incluso si el compilador
p no soporta
p OpenMP!)
p )
Que se aplican a bloques estructurados: una o ms
sentencias con un ppunto de entrada y uno de salida
Se apoya en threads, para la paralelizacin (modelo SPMD)
O MP se bbasa en lla paralelizacin
OpenMP l li i de d bucles
b l (datos)
(d )
Mismo cdigo fuente para secuencial y paralelo
Se protege con el preprocesador: #ifdef _OPENMP .
Los pprototipos
p de funciones y los tipos
p estn en el fichero:
#include <omp.h>
Puede haber interbloqueos
q y carreras!
Tambin soporta vectorizacin y coprocesadores
AC : MP: Introd. a OpenMP 4
Modelo de programacin de OpenMP
Modelo de paralelismo: Fork-Join
El programa comienza con un solo thread (maestro)
El maestro crea threads segn necesidad

AC : MP: Introd. a OpenMP 5


Ejemplo

// Secuencial: // Paralelo:
void main() void main()
{ {
double Res[1000]; double Res[1000];

#pragma omp parallel for


for(int i=0;i<1000;i++) for(int i=0;i<1000;i++)
do_huge
g _comp(Res[i]);
p do_huge
g _comp(Res[i]);
p
} }

Similar la versin paralela y la secuencial.


secuencial
Pocos cambios, legible y fcil de mantener

ACAR: Introduccin a OpenMP 6


Creacin de threads: Regiones Paralelas
Se declaran con la directiva
#
#pragma ll l [clusulas]
omp parallel [ l l ]
{//cdigo}
Crea N threads que ejecutan en paralelo el mismo cdigo,
solo cambia su ID.
Al final de la regin hay una barrera implcita!
El nmero de threads depende
p de variables internas
(num_threads, max_threads, dynamic)
o de la clusula
c usu numu _t
threads(int)
eads( t)
Si se pone la clusula if, se paraleliza slo si se cumple la
condicin:parallel if(N>100)

AC : MP: Introd. a OpenMP 7


Regiones Paralelas: Ejemplo

#include omp.h
omp.h
Funciones de librera

double A[1000];
omp_set_num_threads(4);
#pragma omp parallel
{
int ID = omp_get_thread_num();
omp get thread num();
sumarElemA (ID,A);
}
Cada thread llama a sumarElemA para ID=0 .. 3
Una sola
l copia
i de
d A,
A compartida
id por todos
d los
l threads
h d
AC : MP: Introd. a OpenMP 8
Regiones Paralelas: Ejemplo

#include omp.h
omp.h

double A[1000]; clusula

#pragma omp parallel num


num_threads(4)
threads(4)
{
int ID = omp_get_thread_num();
omp get thread num();
sumarElemA (ID,A);
}
Cada thread llama a sumarElemA para ID=0 .. 3
Una sola
l copia
i de
d A,
A compartida
id por todos
d los
l threads
h d
AC : MP: Introd. a OpenMP 9
Distribucin del trabajo: for
Se declara con la directiva
#pragma omp for [clusulas]
for (;;) {//cdigo}

Divide las iteraciones de un bucle entre los threads


di
disponibles.
ibl
Al final hay una barrera implcita,
evitable con clusula nowait
Se puede especificar cmo se reparten las iteraciones entre
los threads:
clusula schedule

AC : MP: Introd. a OpenMP 10


Distribucin del trabajo for: Ejemplo
1. Cdigo
g secuencial for(i=0;i<N;i++)
{a[i] = a[i] + b[i];}

2. Regin Paralela OpenMP #pragma omp parallel


{
di ib i de
distribucin d trabajo
b j
int id, i,Nthrds,istart,iend;
manualmente
id = omp_get_thread_num();
(id, i, Nthrds, Nthrds =omp
omp_get_num_threads();
get num threads();
istart, iend: son istart = id * N / Nthrds;
variables privadas, iend = (id+1) * N / Nthrds;
por qu?
p q deben
serlo?)) for(i=istart;i<iend;i++)
( )
{ a[i] = a[i] + b[i];}
}

3
3. Regin
R i Paralela
P l l OpenMP
O MP #pragma omp parallel
#
y distribucin de trabajo #pragma omp for schedule(static)
for for(i=0;i<N;i++)
{ a[i]
[i] = a[i]
[i] + b[i]
b[i];}
}

AC : MP: Introd. a OpenMP 11


Distribucin del trabajo for: Planificacin
Planificacin con la clusula schedule:
#pragma omp for schedule(..)
schedule (static [,chunk])
Asigna bloques fijos de iteraciones de tamao chunk a cada thread

schedule (dynamic [,chunk])


C d thread
Cada h d coge chunk
h k iteraciones
i i hasta
h terminar
i con todas
d

schedule (guided [,chunk])


Cada
C d thread
th d coge dinmicamente
di i t bloques
bl de
d iteraciones
it i
El bloque inicialmente es grande (n iteraciones sin asignar
dividido por n threads) y va bajando hasta tamaochunk

schedule (runtime)
Planificacin y tamao de bloque determinado por la variable de
entorno OMP_SCHEDULE
OMP SCHEDULE

AC : MP: Introd. a OpenMP 12


Planificacin: Ejemplo
j p
200 iteraciones en 4 threads

AC : MP: Introd. a OpenMP 13


Distribucin del trabajo: sections

Asigna bloques de cdigo a threads.


threads
Ejemplo:
#pragma omp parallel
#pragma omp sections
{
x_calculation();
#pragma omp section
y_calculation();
#pragma omp section
z_calculation();
();
}
Al final hay una barrera (evitable con nowait)

AC : MP: Introd. a OpenMP 14


Gestin de los datos

Modelo de programacin de memoria compartida:


La mayora de las variables son compartidas por defecto
Las variables globales son compartidas
Pero no todas las variables son compartidas:
Al
Algunas ddeben
b ser especficas
fi para cada
d thread
h d
Las variables declaradas dentro de una regin paralela
Las ubicadas en cada pila propia (parmetros y variables
locales) son privadas (cada thread tiene su pila)
Se puede cambiar los atributos de las variables heredadas
del maestro mediante clusulas

AC : MP: Introd. a OpenMP 15


Gestin de los datos

shared: Variable comn a todos los threads


Cuidado: puede ser necesario utilizar regiones crticas

i t Cada
private: C d thread
h d tiene
ti su
copia
i local.
l l
Sin inicializar y valor indefinido tras la regin 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 iteracin o seccin
default: shared, private (FORTRAN) o none

AC : MP: Introd. a OpenMP 16


Gestin de los datos
threadprivate: hace una copia de una variable, privada
para cada
d thread.
h d Existei a lol largo
l de
d lal ejecucin
j i (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 segn op
Al final las copias locales se reducen a una global
Operadores: + * - & | ^ && || min max

AC : MP: Introd. a OpenMP 17


Gestin de los datos: Ejemplos
j p
1. int tmp=0;
#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+1
a[i]=b[i]; // caso n-1 fuera bucle

3. double ave=0.0, A[MAX], int i;


#pragma omp parallel for \
schedule
h d l ( (static)reduction(+:ave)
t ti ) d ti ( )
for (i=0; i<MAX; i++)
ave+= A[i];
ave = ave/MAX
/MAX

AC : MP: Introd. a OpenMP 18


Gestin de los datos
1. int counter = 0; // N tareas ejecutadas por cada hilo
#pragma omp threadprivate(counter)

2
2. #pragma omp threadprivate(work
threadprivate(work,size)
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);
res = res + Z;
}

ACAR: Introduccin a OpenMP 19


Sincronizacin
critical [name]: Definicin de una regin crtica.
Los threads esperan al comienzo de la regin crtica hasta que no
haya ningn hilo ejecutando una regin crtica con el mismo
b Todas
nombre. T d lasl que no tienen
ti nombre,
b se consideran
id que tienen
ti
un mismo nombre no especificado

Atomic [read|write|update|capture]: Asegura una


actualizacin atmica. Por defecto update
Lectura
L t atmica:
t i v = x;
Escritura atmica: x = expr; //expr no atmica
Actualizacin atmica: x = x binop expr;
Captura atmica: v = x binop= expr; // x atmico

AC : MP: Introd. a OpenMP 20


Sincronizacin
barrier: Implementa una barrera

ordered: Asegura que las iteraciones se ejecutan en el


mismo orden que en secuencial: evtese en lo posible!!

master: Slo el maestro ejecuta dicho cdigo, los dems se lo


saltan. Sin barrera.

g Un solo thread ejecuta


single: j dicho cdigo,
g , tiene una barrera
implcita. Con copyprivate puede hacer visible a los dems
threads los clculos hechos.

AC : MP: Introd. a OpenMP 21


Sincronizacin: Ejemplos
1. #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 toque
printf(%d\n",
printf( %d\n , a); //impresin resultados ordenada
}
2. #pragma omp threadprivate(x, y)
void init(float a
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 qlock
enqueue(job);

#pragma omp critical qlock
dequeue(job);

AC : MP: Introd. a OpenMP 22


Sincronizacin
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


Tareas

A partir de OpenMP 3.0


30
Permite definir una task: conjunto de cdigo y datos
a ejecutar:
j t
#pragma omp task firstprivate(my_pointer)
(void) do
do_independent_work
independent work (my
(my_pointer);
pointer);
Si hay algn thread disponible se pone a ejecutarla, si
no espera uno libre.
Se espera por ellas en las barreras implcitas y
explcitas

ACAR: Introduccin a OpenMP 24


OpenMP 4.0
40
Est disponible OpenMP 4.0 (http://www.openmp.org)
Dos cambios importantes: vectorizacin y coprocesadores
Vectorizacin: nuevo #pragma omp simd para vectorizar
bucles. Toma la idea de Intel (icc). Con clasulas
Busca aprovechar las unidades vectoriales: MMX, SSE, AVX,
MIC) Se podr combinar con regiones paralelas:
MIC).
#pragma omp parallel for simd
Coprocesadores: Se busca aprovechar las GPUs y MICs,
MICs de
gran potencia de clculo.
Se 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
OpenMP de pago para GPUs
ACAR: Introduccin a OpenMP 25
Funciones de biblioteca:
Entorno de Ejecucin
Gestin de threads
void omp_set_num_threads(int)
int
t omp
o p_get_
get num
u _tthreads(void)
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)
omp set nested(bool)
bool omp_get_nested(void)

AC : MP: Introd. a OpenMP 26


Funciones de biblioteca:
Entorno de Ejecucin y Cerrojos
Cerrojos
void omp_init_lock(lock)
void omp_destroy_lock(lock)
void omp_set_lock(lock)
void omp_unset_lock(lock)
void
oid omp_test_lock(lock)
omp test lock(lock)
En una regin paralela?
bool omp_in_parallel(void)
omp in parallel(void)
Nmero procesadores:
int omp
omp_num_procs(void)
num procs(void)
Tomar tiempos
omp
p_g
get_wtime(), omp
p_g
get_wtick()

AC : MP: Introd. a OpenMP 27


Variables del Entorno del Ejecucin

OMP SCHEDULE schedule[,


OMP_SCHEDULE schedule[, chunk
chunk_size]
size]
OMP_NUM_THREADS int_literal // Mximo
OMP_DYNAMIC bool
b l //
//Ajusta
j el
l nmero
d
de
hilos en cada regin paralela
OMP_NESTED bool
OMP_PROC_BIND bool
OMP_STACKSIZE int [B|K|M|G}
OMP WAIT POLICY passive || active
OMP_WAIT_POLICY
OMP_THREAD_LIMIT int

AC : MP: Introd. a OpenMP 28


Compilacin
Incluir el fichero de cabecera: #include <omp.h>
p

Se activa _OPENMP

Compilador de GCC:
gcc -fopenmp
gfortran -fopenmp
Compilador de Intel:
icc -openmp
ifort openmp

AC : MP: Introd. a OpenMP 29


Ejemplo del clculo de Pi
Por clculo nmerico:
1 4.0

0 1 x 2
dx

Se aproxima como:
N

F ( x )x
i 0
i

con F(xi) el alto a mitad del


intervalo y x el ancho del
intervalo

AC : MP: Introd. a OpenMP 30


Ejemplo del clculo de Pi : Secuencial

static long num_steps = 100000;


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

AC : MP: Introd. a OpenMP 31