TEMA 5: PARALELISMO A NIVEL DE HILOS, TAREAS Y … · 2013-11-24 · TEMA 5: PARALELISMO A NIVEL DE...
Transcript of TEMA 5: PARALELISMO A NIVEL DE HILOS, TAREAS Y … · 2013-11-24 · TEMA 5: PARALELISMO A NIVEL DE...
TEMA 5: PARALELISMO A
NIVEL DE HILOS, TAREAS Y
PETICIONES (TLP, RLP)
(primera parte).
SISTEMAS PARALELOS Y DISTRIBUIDOS. 3º GIC
www.atc.us.es
Dpto. de Arquitectura y Tecnología de
Computadores. Universidad de Sevilla
1
INDICE
• 5.1. Conceptos básicos.
• 5.2. Taxonomía y modelos de procesamiento paralelo.
– 5.5. Multiprocesadores con memoria centralizada.
– 5.6. Multiprocesadores con memoria distribuida.
• 5.3. Caracterización de las aplicaciones y Modelos de
programación paralela.
• 5.4. Redes y topologías de interconexión.
• 5.7. Sincronización y consistencia de memoria.
• 5.8. Sistemas multicomputadores para HPC.
• 5.9. Sistemas distribuidos para servicios y
almacenamiento de datos (WSC).
SPD. Tema 5. 2
ESQUEMA DE MULTIPROCESADOR
SPD. Tema 5. 3
Remoto Local
Multiprocesador: término general
Componentes del tiempo de ejecución
SPD. Tema 5 . 4
Hallar
Areal,
Aideal
Argumentos a favor de Multiprocesadores
SPD. Tema 5 . 5
Move to multi-processor
RISC
CISC
Single Processor Performance
Puntos débiles de Multiprocesadores (I)
– Recordar Ley de Amdahl
Ej: queremos conseguir una aceleración de 80, con
100 procesadores ¿Qué fracción del programa debe
ser paralela?
EJ : Un compilador intenta paralelizar un código, y lo
consigue en la mitad del programa
SPD. Tema 5 . 6
75,99F
21
2
*2
1
2
1
1
1
1
N
N
NN
FF
A
Puntos débiles de Multiprocesadores (II)
• Difícil extracción de paralelismo: – “Artesanal”
– Automática sólo si es evidente
– Difícil analizar si una aplicación es paralelizable.
• Lentitud en las comunicaciones – Si un procesador necesita un dato remoto alta
latencia, del orden de microsegundos
(Latencia a memoria local es del orden de pocos ns)
SPD. Tema 5 . 7
5.2. Taxonomía y modelos de procesamiento paralelo
• Clasificación de Flynn (años 60)
– Single / Multiple
– Instruction / Data (flows)
• SISD
• SIMD
• MISD
• MIMD
• PUNTOS CLAVE EN EL DISEÑO:
– Red de interconexión
– La forma de organizar la jerarquía de memoria
SPD. Tema 5. 8
5.2. Taxonomía y modelos de procesamiento paralelo
• Según Organización de la memoria principal
SPD. Tema 5. 9
UMA No tiene
sentido
MPM NUMA
Disposición
lógica
Disposición
física
Espacio direcc.
compartido
Espacio
disjunto de direcc.
Memoria
centralizada
Memoria
distribuida
Igual software,
distinto hardware.
Threads en Paralelo
Procesos
en Paralelo
UMA (Uniform Memory Access) –Tiempo de acceso uniforme para toda dirección
–Tb .llamados SMP’s (Multiprocesadores simétricos)
–Ej: casi todos los multicore actuales
–Cuello de botella: acceso a memoria principal : •Grandes cachés en cada procesador
•AB solicitado por cada procesador crece cada vez más
•Número de procesadores no puede ser alto. Hoy N 32.
SPD. Tema 5. 10
Memoria
Principal E/S
Caché: 1 ó
más niveles
Caché: 1 ó
más niveles
Caché: 1 ó
más niveles
Caché: 1 ó
más niveles
P1 P2 P3 P4
Subsistema de interconexión
simple: latencia baja y constante
NUMA (NonUniform Memory Access)
• Tiempo de acceso a memoria No uniforme
• Ventaja: compatibles con UMA (se aprovecha el código)
– Hace 10 años poco habituales: supercomputadores investigación
– Hoy: Intel Core con QuickPath Interconnect, AMD Opteron con
HyperTransport
• Otros diseños posibles: COMA (Caché Only Memory
Architecture) y mixtos (investigación)
SPD. Tema 5. 11
Cachés y
memoria
Cachés y
memoria
Cachés y
memoria
Cachés y
memoria
P1 P2 P3 P4
Subsistema de interconexión
complejo: latencia alta
Coherencia entre cachés
• Comunicación implícita (variables compartidas)
• Una misma línea replicada en varios
procesadores
Hard adicional para solucionarlo.
• En UMA: Protocolos de husmeo (snooping):
– Protocolo ISX (y otros): similar al de Copy Back
• Línea Inválida (Invalid)
• Línea Compartida (Shared)
• Línea eXclusiva (eXclusive)
• En NUMA: coherencia más difícil de mantener en
hard: directorios
• CUIDADO: falsas comparticiones (false sharing).
SPD. Tema 5. 12
2 cores ejecutan:
P1 P2
a[0]++; a[0]++;
a[1]++; a[2]++;
MPM (Message Passing Machines)
– Espacio de direcciones de memoria distribuido
– Cada procesador es un computador independiente
del resto: “multicomputador”
– Fácilmente escalable (excepto AB red)
– Comunicación explícita a través de mensajes (igual
que la comunicación entre procesos del S.O.).
SPD. Tema 5. 13
Cachés y
memoria
Cachés y
memoria
Cachés y
memoria
Cachés y
memoria
P1 P2 P3 P4
Subsistema de interconexión complejo:
paso de mensajes (latencia muy alta)
Herramientas de programación
• Muchos intentos (y siguen…)
• Lenguaje de programación paralelo:
– No es factible: Difícil de imponer
• Espacio de direcciones compartido – OpenMP: estándar (varios fabricantes importantes:
HP, IBM, SUN, SG...) de directivas del precompilador.
• Espacio de direcciones disjuntos: clusters
de computación. – Librería Message Passing Interface (MPI):
especificación para librerías de paso de mensajes
SPD. Tema 5 . 14
OpenMP: descripción (I)
• Espacio de direcciones compartido
• Permite paralelismo “incremental”
• Modelo de programación paralela SPMD
(Single Program Multiple Data)
– Todos los threads ejecutan la misma copia del
código.
– A cada thread se le asigna un identificador (tid)
– Para diferenciar lo ejecutado por cada thread:
• if (tid == 0) then ... else ...
• constructores específicos de reparto de tareas (work
sharing).
SPD. Tema 5. 15
OpenMP : descripción (II)
• No es un nuevo lenguaje, sino API con:
– directivas para el compilador
• facilita la portabilidad y
• la “paralelización incremental”.
– unas pocas funciones de biblioteca
– algunas variables de entorno
• Un programa puede ser compilado por
compiladores que no soportan OpenMP
– Las directivas son tratadas como comentarios
e ignoradas.
– ATENCIÓN: No olvidar “Compatibilidad
OpenMP” en el compilador
SPD. Tema 5. 16
Sintaxis de OpenMP
• Pragma en C y C++: #pragma omp construct [clause [clause]…]
• En Fortran, directivas : C$OMP construct [clause [clause]…]
!$OMP construct [clause [clause]…]
*$OMP construct [clause [clause]…]
SPD. Tema 5. 17
Claves del diseño de una aplicación (I)
1. directivas que especifican una región
paralela (código replicado)
2. reparto de tareas (específicas para cada
thread)
3. sincronización entre threads
• Fácil para bucles (paralelizables directa o
indirectamente)
– Sólo paso 1 (2 y 3 los introduce el compilador)
SPD. Tema 5. 18
Claves del diseño de una aplicación (II)
1. Partiendo de un programa serie, buscar
partes del código paralelizables:
– estructuras de control paralelo (bucles for)
– reparto de tareas
2. Incluir la comunicación entre hilos
– a través de variables compartidas (Cuidado
con ámbito de las variables)
3. Sincronizar
– exclusión mutua
– barreras
SPD. Tema 5. 19
Programa sencillo
Programa Secuencial void main() {
double a[1000],b[1000],c[1000];
for (int i = 0; i< 1000; i++){
a[i] = b[i] + c[i];
}
}
Programa Paralelo void main() {
double a[1000],b[1000],c[1000];
#pragma omp parallel for
for (int i = 0; i< 1000; i++){
a[i] = b[i] + c[i];
}
} SPD. Tema 5. 20
Programa sencillo: explicación (I) void main() {
double a[1000],b[1000],c[1000];
/*Un único pragma, pero el compilador debe
previamente crear tantos hilos P como
permita en paralelo el procesador */
/* debe decidir que hacer con las variables
a[],b[],c[],i: ¿crea copias y las
replica?¿no crea copias:son compartidas?*/
#pragma omp parallel for
/*aquí debe trocear en bucle en P hilos */
for (int i = 0; i< 1000; i++){
a[i] = b[i] + c[i];
}
} 0 250 500 750 1000
SPD. Tema 5. 21
Programa sencillo: explicación (II) #pragma omp parallel for
/*Troceado por defecto (existen otros)*/
//Supongamos P=4
//Hilo 0
for (int i = 0; i< 250; i++){
a[i] = b[i] + c[i]; }
//Hilo 1
for (int i = 250; i< 500; i++){
a[i] = b[i] + c[i]; }
//Hilo 2
for (int i = 500; i< 750; i++){
a[i] = b[i] + c[i]; }
//Hilo 3
for (int i = 750; i< 1000; i++){
a[i] = b[i] + c[i]; }
SPD. Tema 5. 22
Regiones paralelas y críticas
• El modelo de programación paralela es
Fork - Join.
– El master thread genera P threads que se
ejecutan en paralelo.
SPD. Tema 5. 23
Critical regions
OpenMP runtime library
omp_get_num_threads()
• devuelve el número actual de threads
omp_get_thread_num()
• devuelve el identificador de ese thread
omp_set_num_threads(n)
• activa el número de threads
SPD. Tema 5. 24
¿Qué parte le corresponde al hilo 0 de este
bucle (usar estas func.)? ¿Y al hilo k ? for (int i = 0; i< n; i++){…}
Declarando Ámbito de datos (I)
• shared: variable es compartida por todos los
procesos. Ej: vectores del proceso.
• private: Cada proceso tiene una copia
#pragma omp parallel for
shared(a,b,c,n) private(i, temp)
for (i = 0; i < n; i++) {
temp = a[i]/b[i];
a[i] = b[i] + temp * c[i];
}
• Hay reglas para decidir por defecto el ámbito,
pero mejor no arriesgarse
• Lo peligroso son las escrituras
• CUIDADO: false sharing SPD. Tema 5. 25
¿Qué pasa si n=2;
float a[2], b[2], c[2];?
Declarando Ámbito de datos (II)
• Variables REDUCTION: operaciones
colectivas sobre elementos de un array
• Operadores: + * - & | ^ && || asum = 0.0;
aprod = 1.0;
#pragma omp parallel for reduction(+:asum)
reduction(*:aprod)
for (i = 0; i < n; i++) {
asum = asum + a[i];
aprod = aprod * a[i];
}
SPD. Tema 5. 26
Planificación de Tareas: SCHEDULE (I)
Diferentes formas de asignar iteraciones a
threads
• schedule(static [,chunk])
– “chunk” iteraciones se asignan de manera
estática a los threads en round-robin
• schedule (dynamic [,chunk])
– Cada thread toma “chunk” iteraciones cada
vez que está sin trabajo
• schedule (guided [,chunk])
– Cada thread toma progresivamente menos
iteraciones (dinámicamente) SPD. Tema 5. 27
Planificación de Tareas: SCHEDULE (II)
• igual num iteraciones para static, dynamic.
• exponencialm. decreciente para guided
• Hilo 0 1 2 0 1 2 0 1 2
SPD. Tema 5. 28
a
b
c
d
e
f
g
h
i
Static
a
b
c
d
e
f
g
h
i
Dynamic
a
b
c
d
e f g
Guided
Planificación de Tareas: SCHEDULE (III)
RECUERDA:
• Static : menos coste / mejor localidad datos
• Dynamic: más coste / carga más equilibrada
SPD. Tema 5. 29
Static: bucles simples
Dynamic: si carga varía
según la iteración
Regiones Paralelas
#pragma omp parallel
{
/* Bloque básico replicado (ejecutado) por
cada thread */
}
SPD. Tema 5. 30
Reparto de tareas en f(tid).
Pag 15
Pero “carrera” entre todos
¿Qué se imprime?
Work Sharing (reparto de tareas)
1. Directiva for,
– para repartir la ejecución de las iteraciones de un
bucle entre todos los threads (bloques básicos y
número de iteraciones conocido).
– Se suele usar junto a omp parallel for
2. Directiva sections,
– para definir “manualmente” trozos o secciones de
una región paralela a repartir entre los threads en
función del tid.
3. Directiva single,
– para definir un trozo de código que sólo debe
ejecutar un thread.
SPD. Tema 5. 31
Secciones (una por hilo) #pragma omp parallel sections
{
#pragma omp section
{
printf ("id s1=%d,\n“,omp_get_thread_num());
for (i=0; i<tam/2; i++)
y[i] = a*x[i] + y[i];
}
#pragma omp section
{
printf ("id s2=%d,\n“,omp_get_thread_num());
for (i=tam/2; i<tam; i++)
y[i] = a*x[i] + y[i];
}
}
SPD. Tema 5. 32
Escribir esto con #pragma omp parallel
(ver 2 pag. antes)
Directiva single #pragma omp parallel
{
... ;
#pragma omp single
inicializar(A);
#pragma omp for // todos
// los threads deben alcanzar
// la directiva paralela
for(i=0; i<N; i++)
A[i] = A[i] * A[i] + 1;
... ;
#pragma omp single
copiar(B,A);
} SPD. Tema 5. 33
single
for
single
parallel
Regiones paralelas y críticas
• Los threads se comunican utilizando variables
compartidas.
• El uso inadecuado de variables compartidas
origina “carreras” (data-race)
• Uso de sincronización o exclusión para evitarlas
• NOTA: sincronización es muy costosa en
tiempo: usar lo menos posible
SPD. Tema 5. 34
Exclusión Mutua: Sección Crítica
#pragma omp parallel shared(x,y)
{ …
#pragma omp critical (section1)
actualiza(x); //only one thread
…
usa(x);
…
#pragma omp critical(section2)
actualiza(y); //only one thread
…
usa(y);
} SPD. Tema 5. 35
¿Qué ocurre si no se
declara la sección crítica?
Exclusión Mutua: Sección Crítica EJ.
SPD. Tema 5. 36
¿Qué pasa si cnt++
no se declara como
crítico?
Sincronización: Barreras
• Los threads se detienen hasta que alcancen la barrera nt=omp_get_num_threads();
#pragma omp parallel private (i, id)
{
id=omp_get_thread_num();
for (i=id*tam/nt; i<(id+1)*tam/nt; i++) {
y[i] = a*x[i] + y[i];
}
#pragma omp barrier
// aquí seguro que todo y[] está actualizado
for (i=id*tam/nt; i<(id+1)*tam/nt; i++) {
z[i] = b + y[tam-i-1];
}
}
SPD. Tema 5. 37
¿Se pueden fusionar
los bucles? ¿Y si
fuera y[i]?
Cálculo 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=1;i<= num_steps; i++){
x = (i-0.5)*step;
sum = sum + 4.0/(1.0+x*x);
}
pi = step * sum;
}
SPD. Tema 5. 38
04
)(1
1
0)0(4
)1(
1
1)(
1
0
1
0 2
2
xarctgx
arctg
arctg
xxgarct
Cálculo de PI: Omp Reduction #include <omp.h>
static long num_steps = 100000; double step;
void main () {
int i; double x, pi, sum = 0.0;
step = 1.0/(double) num_steps;
omp_set_num_threads(2);
#pragma omp parallel for reduction(+:sum)
private(x)
for (i=1;i<= num_steps; i++){
x = (i-0.5)*step;
sum = sum + 4.0/(1.0+x*x);
}
pi = step * sum;
} SPD. Tema 5. 39
Cálculo de PI: Omp “manualmente” #include <omp.h>
static long num_steps = 100000; double step;
void main () {
int i; double x, pi, sum[2];
step = 1.0/(double) num_steps;
omp_set_num_threads(2);
#pragma omp parallel
{ double x; int id;
id = omp_get_thread_num();
//for (i=id+1, sum[id]=0.0;i<= num_steps; i=i+2){
for (i=id* num_steps/2, sum[id]=0.0;
i<= (id+1)* num_steps/2; i++ ) {
x = (i+0.5)*step;
sum[id] += 4.0/(1.0+x*x);
}
}
for(i=0, pi=0.0;i<2;i++) pi+=sum[i]*step;
} SPD. Tema 5. 40
¿Qué le pasa al ‘for’
comentado?
Hilo 0
Hilo 1