Arquitecturas Paralelas IF - EHU Arquitecturas Paralelas 8. Paralelización de bucles. Reparto de tareas. - Introducción - Paralelización de bucles - Mecanismos de sincronización - Optimizaciones principales - Reparto de las iteraciones - Secciones paralelas
69
Embed
Arquitecturas Paralelas IF - EHU Arquitecturas Paralelas 8. Paralelización de bucles. Reparto de tareas. - Introducción - Paralelización de bucles - Mecanismos.
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Arquitecturas Paralelas IF - EHU
Arquitecturas Paralelas
8. Paralelización de bucles. Reparto de tareas.
- Introducción- Paralelización de bucles- Mecanismos de sincronización- Optimizaciones principales- Reparto de las iteraciones- Secciones paralelas
Arquitecturas ParalelasIF - EHU
P. Bucl. 28
Identificar qué tareas pueden ejecutarse en paralelo y cuáles no (análisis de dependencias).Sincronizar los procesos.Repartir los procesos a los procesadores.
Objetivo: ejecutar los programas P veces más rápido; caso particular: bucles.
Hacerlo de manera eficiente.
Introducción
Arquitecturas ParalelasIF - EHU
P. Bucl. 38
Tipos de paralelismo (1)
(a) Paralelismo de datos
do i = 1, 1000 do i = 1001, 2000 do i = 2001, 3000A(i) = func(i) A(i) = func(i) A(i) = func(i)
enddo enddo enddo
P0 P1 P2
do i = 1, 3000A(i) = func(i)
enddo
Introducción
Arquitecturas ParalelasIF - EHU
P. Bucl. 48
Tipos de paralelismo (1)
(b) Paralelismo de función
Introducción
P0 P1
F1
F2
F3
F4
Arquitecturas ParalelasIF - EHU
P. Bucl. 58
Tipos de paralelismo (2)
▪ grano fino (fine grain) tareas “pequeñas” / mucha comunicación
▪ grano medio
▪ grano grueso (coarse grain)
tareas “grandes” / poca comunicación
▪ grado de paralelismo
Introducción
Arquitecturas ParalelasIF - EHU
P. Bucl. 68
¿Dependencias entre tareas?
Sincronización
- global (barreras)- punto a punto (eventos)
Introducción
P0 P1
F1
F2
F3
F4
Arquitecturas ParalelasIF - EHU
P. Bucl. 78
Dos modelos
▪ Maestro-esclavo
Un thread master genera P threads para ser ejecutados en paralelo, que “mueren” al terminar su tarea.
▪ SPMD (Single-Program-Multiple-Data)
Se ejecutan P copias iguales independientes. Las tareas se diferencian mediante el pid del proceso.
Introducción
Arquitecturas ParalelasIF - EHU
P. Bucl. 88
Paralelización de bucles
grano fino / medioreparto de iteraciones del bucleanálisis de dependencias
Hacerlo de manera eficiente. ¿El programador o el compilador?
Introducción
Arquitecturas ParalelasIF - EHU
P. Bucl. 98
Salvo casos muy obvios, la paralelización del código (análisis de dependencias, reparto de tareas, etc.) sigue siendo responsabilidad del programador.
Por ello, vamos a ver algunas de las opciones más habituales a la hora de paralelizar bucles de manera eficiente.
Introducción
Arquitecturas ParalelasIF - EHU
P. Bucl. 108
Se necesita que una fracción importante del código pueda ejecutarse en paralelo. ¡No olvides la ley de Amdahl!
Paralelizar (como vectorizar) código implica cambiar el orden original de las instrucciones del bucle. Por tanto, tenemos que analizar las dependencias entre las instrucciones del bucle.
Introducción
Arquitecturas ParalelasIF - EHU
P. Bucl. 118
Ejemplo:
do i = 0, N-1
A(i) = A(i) + 1
enddo
P0: L0 +0 S0P1: L1 +1 S1P2: L2 +2 S2… ...
En paralelo
Introducción
L0 +0 S0 L1 +1 S1 L2 +2 S2 ...
Arquitecturas ParalelasIF - EHU
P. Bucl. 128Introducción: depend.
dependencia
RAW
i: A =...
j: = A
antidependencia
WAR
i: = A...
j: A =
dependen. de salida
WAW
i: A =...
j: A =
i j i j i j
dependencias verdaderas dependencias de nombre
Arquitecturas ParalelasIF - EHU
P. Bucl. 138
Bucles
+ Grafo de dependencias+ Distancia de la dependencia
do i = 2, N-21 A(i) = B(i) + 22 C(i) = A(i-2) + A(i+1)
Si todas las dependencias son de distancia 0 (las iteraciones son independientes), éstas se pueden repartir como se quiera entre los procesadores, sin tener que sincronizarlas: doall.
Si hay dependencias entre iteraciones, pero todas van hacia adelante, se pueden sincronizar mediante barreras: forall (o doall + barrier).
Si las dependencias forman ciclos, hay que utilizar sincronización punto a punto: doacross.
Paralelización de bucles
Arquitecturas ParalelasIF - EHU
P. Bucl. 278
Las iteraciones son independientes, por lo que el reparto puede hacerse como se quiera: doall.
Bucles doall
do i = 0, N-1C(i) = C(i) * C(i)A(i) = C(i) + B(i)D(i) = C(i) / A(i)
Hay dependencias entre iteraciones, pero todas van “hacia adelante”: forall.
Cada dependencia puede sincronizarse con una barrera: los procesos esperan a que todos hayan ejecutado una determinada instrucción antes de pasar a ejecutar la siguiente.
Hay más sincronización que la estrictamente necesaria, pero es sencillo de implementar.
Bucles forall
Arquitecturas ParalelasIF - EHU
P. Bucl. 298Bucles forall
do i = 1, N-1C(i) = C(i) * C(i)A(i) = C(i) + B(i)D(i) = C(i-1) / A(i)
if (B(i) > 0) then A(i) = A(i) + B(i) post (vA,i) wait (vA,i-1) C(i) = A(i-1) / 2
endif
enddoacross
else post (vA,i)
endif1
2
A,1
0
Instrucciones if
Arquitecturas ParalelasIF - EHU
P. Bucl. 388
Cómo sincronizar las instrucciones
• mediante vectores de eventos (post/wait)
- inicialización- tamaño (memoria)- ojo con la falsa compartición
• mediante contadores
Mecanismos de sincron.
Arquitecturas ParalelasIF - EHU
P. Bucl. 398
Contadores de sincronización (uno por cada depen-dencia)
- las instrucciones van “acabando” en orden estricto, e incrementan el contador.
- cA = j han terminado todas las iteraciones hasta la j, y no la j+1.
i = 0 1 2 3 4 5 6 7 8 9...
vA(i) = 1 1 1 0 1 0 1 1 0 0...cA = 2
Contadores de sincron.
Arquitecturas ParalelasIF - EHU
P. Bucl. 408
Para sincronizar una dependencia mediante un contador:
- tras ejecutar la iteración i, esperar a que el valor del contador sea i-1 (es decir, a que se haya ejecutado esa instrucción hasta la iteración i-1).
wait (cA,i-1) → esperar a que cA = i-1
- incrementar el contador, para indicar que también se ha ejecutado la iteración i.
post (cA,i) → cA := cA + 1 (cA := i)
Contadores de sincron.
Arquitecturas ParalelasIF - EHU
P. Bucl. 418
doacross i = 3, N-1
wait (vD,i-3)
C(i) = C(i) * D(i-3)
post (vC,i)
A(i) = C(i) + B(i)
wait (vC,i-1)
D(i) = C(i-1) / A(i)
post (vD,i)
enddoacross
do i = 3, N-1C(i) = C(i) * D(i-3)A(i) = C(i) + B(i)D(i) = C(i-1) / A(i)
enddo
1
2
3
C, 0
A, 0 C,1
D,3 1 1 12 2 23 3 3
1 1 1 2 2 2 3 3 3
doacross i = 3, N-1wait (cD,i-3)C(i) = C(i) * D(i-
do j = 1, 2N-1 doall i = max(1,j-N+1), min(j,N) A(i,j-(i-1)) = A(i-1,j-(i-1)) + A(i,j-1-(i-1)) enddoallenddo
9. Skew
do i = 1, N do j = 1, N A(i,j) = A(i-1,j) + A(i,j-1) enddoenddo
Principales optimizaciones
Arquitecturas ParalelasIF - EHU
P. Bucl. 568
10. Otras optimizaciones típicas
Aumento del tamaño de grano y reducción del overhead de la paralelización.
- Juntar dos bucles en uno (¡manteniendo la semántica!): fusión.- Convertir un bucle de dos dimensiones en otro de una sola dimensión: colapso o coalescencia.…
Principales optimizaciones
Arquitecturas ParalelasIF - EHU
P. Bucl. 578
¿Cómo se reparten las iteraciones de un bucle entre los procesadores?Si hay tantos procesadores como iteraciones, tal vez una por procesador.
Pero si hay menos (lo normal), hay que repartir. El reparto puede ser:
estático: en tiempo de compilación.dinámico: en ejecución.
Reparto de iteraciones
Arquitecturas ParalelasIF - EHU
P. Bucl. 588
El objetivo: intentar que el tiempo de ejecución de los trozos que se reparten a cada procesador sea similar, para evitar tiempos muertos (load balancing).
En todo caso, OJO con las dependencias (sincronización), el tamaño de grano, la localidad de los accesos y el coste del propio reparto.
Reparto de iteraciones
Arquitecturas ParalelasIF - EHU
P. Bucl. 598
Planificación estática
Qué ejecuta cada procesador se decide en tiempo de compilación. Es por tanto una decisión prefijada.
Cada proceso tiene una variable local que lo identifica, pid [0..P-1].
Dos opciones básicas: reparto consecutivo y reparto entrelazado.
Reparto de iteraciones
Arquitecturas ParalelasIF - EHU
P. Bucl. 608
- No añade carga a la ejecución de los threads.
- Pero no asegura el equilibrio de la carga entre los
procesos.
- Permite cierto control sobre la localidad de los accesos a
cache.
▪ Consecutivo
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
0 0 0 0 1 1 1 1 2 2 2 2 3 3 3 3
▪ Entrelazado
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
0 1 2 3 0 1 2 3 0 1 2 3 0 1 2 3
principio = pid * N/Pfin = (pid+1) * N/P – 1
do i = principio, fin...
enddo
do i = pid, N, P...
enddo
Reparto de iteraciones
Arquitecturas ParalelasIF - EHU
P. Bucl. 618
Equilibrio en el reparto de carga
1-20
21-40
41-60
61-80
estático (fijo)
Tej
asignación dinámica de
una nueva tarea
1-10
21-30
11-20
31-40
Tej
do i = 1, 80if (A(i) > 0) calcular()
enddo
Reparto de iteraciones
Arquitecturas ParalelasIF - EHU
P. Bucl. 628
Planificación dinámica
Para intentar mantener la carga equilibrada, las tareas se van escogiendo en tiempo de ejecución de un cola de tareas. Cuando un proceso acaba con una tarea (un trozo del bucle) se asigna un nuevo trozo.
Dos opciones básicas: los trozos que se van repartiendo son de tamaño constante o son cada vez más pequeños.
Reparto de iteraciones
Arquitecturas ParalelasIF - EHU
P. Bucl. 638
Las iteraciones se reparten una a una, o por trozos de tamaño Z.
Self / Chunk scheduling
Añade carga a la ejecución de los threads. Hay que comparar ejecución y reparto.
LOCK (C); mia = i; i = i + Z; Z = 1 selfUNLOCK (C);
while (mia <= N-1)
endwhile
do j = mia, min(mia+Z-1, N-1) ...enddoLOCK (C) mia = i; i = i + Z;UNLOCK (C)
Reparto de iteraciones
Arquitecturas ParalelasIF - EHU
P. Bucl. 648
Los trozos de bucle que se reparten son cada vez más pequeños según nos acercamos al final.
Guided / Trapezoidal
▪ Guided : parte proporcional de lo que queda por ejecutar:
Zs = (N – i) / P (entero superior)
que equivale a:
Zi = Zi-1 (1 - 1/P)
Reparto de iteraciones
Arquitecturas ParalelasIF - EHU
P. Bucl. 658
▪ Trapezoidal: reduciendo el trozo anterior en una constante: Zi = Zi-1 - k
op. de planificación
Z1
Zn
1 n2 i
k
Z2
)(21
22 1
22111
1
1
n
nnnn
s
ns ZZN
ZZkN
k
ZZZZn
ZZZ
Reparto de iteraciones
Arquitecturas ParalelasIF - EHU
P. Bucl. 668
En general, el reparto dinámico busca un mejor equilibrio en el reparto de carga, pero:
- hay que considerar la carga que se añade (overhead), en relación al coste de las tareas que se asignan.
- hay que considerar la localidad en los accesos a los datos y los posibles
problemas de falsa compartición.
Reparto de iteraciones
Arquitecturas ParalelasIF - EHU
P. Bucl. 678
Ejemplo de reparto (1.000 iteraciones, 4 procesadores):