Publicado el 8 de Septiembre del 2017
655 visualizaciones desde el 8 de Septiembre del 2017
153,1 KB
5 paginas
Creado hace 12a (10/07/2012)
Arquitectura de Computadores
Arquitectura de Computadores::
Práctica de Multiprocesadores
Práctica de Multiprocesadores
Introducción a OpenMP
Introducción a
OpenMP
Índice
Introducción
1.
2. Regiones Paralelas:
a) For
b) Sections
3 Distribución del trabajo
3. Distribución del trabajo
4. Gestión de datos
5. Sincronización
6. Tareas
7. Funciones de biblioteca
8. Variables del entorno
9. Ejemplo Π
AC : MP: Introd. a OpenMP
2
1. Introducción
OpenMP se basa en directivas al compilador (¡es
compilable incluso si no se soporta OpenMP!)
Mismo código fuente para secuencial y paralelo
Se protege con el preprocesador: _OPENMP
Basado en paralelización de bucles (datos)
Basado en paralelización de bucles (datos)
Se aplica a bloques estructurados
1. Introducción
Modelo de paralelismo: Fork-Join
Un maestro crea y gestiona threads según
necesidad:
• 1 entrada, 1salida
Se apoya en threads, para la paralelización
Pensado para memoria compartida
Modelo SPMD
¡Puede haber interbloqueos y carreras!
AC : MP: Introd. a OpenMP
3
AC : MP: Introd. a OpenMP
4
Ejemplo
Regiones Paralelas
// Secuencial:
void main()
{
double Res[1000];
// Paralelo:
void main()
{
double Res[1000];
for(int i=0;i<1000;i++)
do_huge_comp(Res[i]);
}
#pragma omp parallel for
for(int i=0;i<1000;i++)
do_huge_comp(Res[i]);
}
Similar el paralelo y el secuencial.
Pocos cambios, legible y fácil de mantener
AC : MP: Introd. a OpenMP
5
Se declaran con la directiva
#pragma omp parallel
{//código…}
Crea N threads que ejecutan en paralelo el mismo
código solo cambia su ID
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
(num_threads, max_threads, dynamic)
O de la clausula num_threads(int)
Si aparece la clausula “if”, se paraleliza sólo si se
cumple la condición:…parallel if(N>100)…
AC : MP: Introd. a OpenMP
6
1
Regiones Paralelas: Ejemplo
Distribución del trabajo: for
double A[1000];
omp_set_num_threads(4);
#pragma omp parallel
{
int ID = omp_get_thread_num();
sumarElemA (ID,A);
}
Se declaran con la directiva
#pragma omp for
for (;;) {//código…}
Divide las iteraciones de un bucle entre los threads
disponibles.
Al final hay una barrera implicita (evitable: nowait)
Se puede especificar la planificación
Se pueden “agrupar” varios bucles en uno, juntando sus
iteraciones: #pragma omp for collapse (3)
AC : MP: Introd. a OpenMP
7
AC : MP: Introd. a OpenMP
8
Distribución del trabajo: Ejemplo for
Distribución del trabajo: for
1. Código secuencial
2.
Región Paralela OpenMP
(id, i, Nthrds, istart, iend:
son variables privadas,
¿por qué? ¿deben serlo?)
3.
Región Paralela
OpenMP y distribución
de trabajo for
for(i=0;i<N;i++)
{a[i] = a[i] + b[i];}
#pragma omp parallel
{
int id, i,Nthrds,istart,iend;
id = omp_get_thread_num();
Nthrds =omp get num threads();
Nthrds omp_get_num_threads();
istart = id * N / Nthrds;
iend = (id+1) * N / Nthrds;
for(i=istart;i<iend;i++)
{ a[i] = a[i] + b[i];}
}
#pragma omp parallel
#pragma omp for schedule(static)
for(i=0;i<N;i++)
{ a[i] = a[i] + b[i];}
thread
Planificación con la clausula schedule:
#pragma omp for schedule(..)
schedule (static [,chunk])
● Asigna bloques fijos de iteraciones de tamaño “chunk” a cada
schedule (dynamic [ chunk])
schedule (dynamic [,chunk])
●
schedule (guided [,chunk])
●
●
schedule (runtime)
●
Cada thread coge dinámicamente bloques de iteraciones
El bloque inicialmente es grande y va bajando hasta
tamaño“chunk”
Cada thread coge “chunk” iteraciones hasta terminar con todas
Planificación y tamaño de bloque determinado por la variable de
entorno OMP_SCHEDULE
AC : MP: Introd. a OpenMP
9
AC : MP: Introd. a OpenMP
10
Distribución del trabajo: for
Distribución del trabajo: sections
Asigna “secciones” a threads. Ejemplo
#pragma omp parallel
#pragma omp sections
{
x_calculation();
#pragma omp section
p g
y_calculation();
#pragma omp section
z_calculation();
p
}
Al final hay una barrera (opción nowait)
AC : MP: Introd. a OpenMP
11
AC : MP: Introd. a OpenMP
12
2
Gestión de los datos
Gestión de los datos
Todos las variables son compartidas (memoria
compartida)
Pero las variables ubicadas en cada pila propia
(parámetros y variables locales) son privadas
( d th
(cada thread tiene su pila)
il )
d ti
Se puede cambiar los ‘atributos’ de las variables
heredadas del maestro mediante cláusulas
shared: Variable común a todos los threads
● Cuidado: puede necesitar regiones críticas
private: Cada thread tiene “su” copia local.
● Sin inicializar e indefinido tras la región paralela
firstprivate: Es private, pero se inicializa con el
valor del ‘original’ (variable del maestro)
lastprivate: Es private, pero al final tiene el valor
que le corresponda en la última iteración
default: shared, private (FORTRAN) o none
AC : MP: Introd. a OpenMP
13
AC : MP: Introd. a OpenMP
14
Gestión de los datos
threadprivate: hace una copia privada de un dato
asociada a cada thread. Existe a lo largo de la
ejecución. en secuencial se ve la copia del maestro
copyin: inicializa los threadprivate con el maestro
copyprivate: pasa el valor dado en un hilo 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
Gestión de los datos
1. #pragma omp parallel private(i) firstprivate(j)
{ i = 3 + func(id);
j = j + 2; }
2. #pragma omp parallel for lastprivate(i)
for (i=0; i<n-1; i++)
a[i]=b[i]; // caso n-1 fuera bucle
a[i] b[i]; // caso n 1 fuera bucle
a[i] = b[i] + b[i+1];
for (i=0; i<n; i++) {
3. #pragma omp parallel for shared(x, y, n) reduction(+:a)
reduction(^:b) reduction(min:c) reduction(max:d)
a += x[i];
b ^= y[i];
if (c < y[i]) c = y[i];
if (d > x[i]) d = x[i];
}
AC : MP: Introd. a OpenMP
15
AC : MP: Introd. a OpenMP
16
Gestión de los datos
1. int counter = 0;
#pragma omp threadprivate(counter)
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);
res = res + Z;
Sincronización
critical: Define una región crítica
atomic: Asegura una actualización atómica
barrier: Implementa una barrera
ordered: Asegura que las iteraciones se ejecutan en
el mismo orden que en secuencial: ¡¡evítese en lo
el 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
single: Un solo thread ejecuta dicho código, tiene
una barrera implícita. Con copyprivate puede hacer
visible a los demás threads los cálculos hechos.
AC : MP: Introd. a OpenMP
17
AC : MP: Introd. a OpenMP
18
3
Sincronización
Sincronización
1. #pragma omp parallel for schedule(dynamic) private(a)
for (i=0; i<N; i++){
a = work(i);
#pragma omp ordered
printf(“%d\n", a); //impresión resultados ordenada
}
2
#pragma omp threadprivate(x y)
2. #pragma omp threadprivate(x, y)
void init(float a, float b ) { // a y b privados
#pragma omp single copyprivate(a,b,x,y)
{
}
}
{
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;
}
scanf("%f %f %f %f", &a, &b, &x, &y);
AC : MP: Introd. a OpenMP
19
AC : MP: Introd. a OpenMP
20
Tareas
Tareas: Ejemplo
A partir de OpenMP 3.0
Permite definir una “task”: conjunto de código y
datos a ajecutar
Si hay algún thread disponible se pone a ejecutarla,
si no espera uno libre.
¿Cómo se pueden paralelizar este código?
while(my_pointer) {
do_independent_work (my_pointer);
my pointer = my pointer >next ;
my_pointer = my_pointer->next ;
} // End of while loop
Permite una flexibilidad imposible antes
Se espera por ellas en las barreras implícitas y
explícitas
Se puede esperar por ellas con taskwait
En general cualquier código con un número
indefinido de iteracciones. Solución bestia: contar
los elementos de la lista y montar un bucle: feo
Solución: Tareas. Puede ser condicional (clausula if)
AC : MP: Introd. a OpenMP
21
AC : MP: Introd. a OpenMP
22
Tareas: Ejemplo
my_pointer = listhead;
#pragma omp parallel
{
#pragma omp single nowait
{
while(my_pointer) {
#pragma omp task firstprivate(my_pointer)
{
(void) do_independent_work (my_pointer);
}
my_pointer = my_pointer->next ;
}
}// End of single - no implied barrier (nowait)
} // End of parallel region - implied barrier
Funciones de biblioteca:
Entorno de Ejecución
Gestión de threads
• void omp_set_num_threads(int)
• int omp_get_num_threads(void)
• int omp_get_thread_num(void)
• int omp_get_max_threads(void)
• void omp set dynamic(bool)
• void omp_set_dynamic(bool)
• bool omp_get_dynamic(void)
• void omp_set_nested(bool)
• bool omp_get_nested(void)
Anidamiento del paralelismo
AC : MP: Introd. a OpenMP
23
AC : MP: Introd. a OpenMP
24
4
Funciones de biblioteca:
Entorno de Ejecución y Cerrojos
Cerrojos
• void omp_init_lock(lock)
• void omp_destroy_lock(lock)
• void omp_set_lock(lock)
• void omp unset lock(lock)
• void omp_test_lock(lock)
_
_
Número procesadores:
¿En una región paralela?
bool omp_in_parallel(void)
int omp_num_procs(void)
omp_get_wtime(), omp_get_wtick()
Tomar tiempos
Variables del Entorno del Ejecución
OMP_SCHEDULE “schedule[, chunk_size]”
OMP_NUM_THREADS int_literal
OMP_DYNAMIC bool
OMP_NESTED bool
OMP PROC BIND bool
OMP_PROC_BIND bool
OMP_STACKSIZE int [B|K|M|G}
OMP_WAIT_POLICY passive || active
OMP_THREAD_LIMIT int
AC : MP: Introd. a OpenMP
25
AC : MP: Introd. a OpenMP
26
Ejemplo del cá
Comentarios de: Práctica de Multiprocesadores Introducción a OpenMP - Arquitectura de Computadores (0)
No hay comentarios