Documentos de Académico
Documentos de Profesional
Documentos de Cultura
PARALELOS
Computacin de Alta Velocidad
A. Arruabarrena J. Muguerza
Konputagailuen Arkitektura eta Teknologia saila
Informatika Fakultatea Euskal Herriko Unibertsitatea
COMPUTADORES
PARALELOS
Computacin de Alta Velocidad
A. Arruabarrena J. Muguerza
Konputagailuen Arkitektura eta Teknologia saila
Informatika Fakultatea Euskal Herriko Unibertsitatea
septiembre 2012
NDICE
Introduccin ......................................................................... 1
Captulo 1. Computadores Vectoriales ............................................... 7
1.1 Qu es un computador vectorial? ................................................................... 7
1.1.1 Algunos problemas ............................................................................................... 10
1.1.1.1 La memoria de un computador vectorial .......................................... 10
1.1.1.2 Unidades funcionales vectoriales ........................................................ 11
1.1.1.3 Registros vectoriales ............................................................................... 11
1.1.1.4 Programas vectoriales ............................................................................ 12
1.1.2 Arquitectura y lenguaje-mquina ...................................................................... 13
vi
NDICE
SMP ...................................................................................... 83
vii
NDICE
Captulo
viii
NDICE
Captulo
ix
NDICE
Captulo
DSM.................................................................................... 241
NDICE
7.3.2.1
7.3.2.2
7.3.2.3
7.3.2.4
7.3.2.5
Captulo
8.2. Estructuras bsicas para expresar el paralelismo de los bucles .............. 290
8.2.1 Bucles sin dependencias entre iteraciones: bucles doall .......................... 290
8.2.2 Bucles con dependencias entre iteraciones ................................................. 291
8.2.2.1 Bucles forall (sincronizacin global .................................................. 292
8.2.2.2 Bucles doacross (sincronizacin punto a punto) .......................... 293
8.2.3 Efecto de las antidependencias y de las dependencias de salida ........... 298
8.2.4 Atencin con las instrucciones if..................................................................... 299
Eliminacin del efecto de las dependencias que no son esenciales ...... 304
Fisin de bucles ................................................................................................... 305
Ordenacin de las dependencias ................................................................... 306
Alineacin de las dependencias (peeling) .................................................... 307
Extraccin de threads independientes (switching) ..................................... 309
Minimizacin de las operaciones de sincronizacin ................................. 310
Tratamiento de bucles (reordenacin...) ........................................................ 311
8.4.7.1 Intercambio de bucles.......................................................................... 311
8.4.7.2 Cambio de sentido................................................................................ 314
8.4.7.3 Desplazamientos (skew) ....................................................................... 314
8.4.7.4 Colapso y coalescencia de bucles .................................................... 315
8.5 Planificacin de bucles (scheduling) ............................................................... 316
8.5.1 Reparto de las iteraciones: consecutivo o entrelazado............................. 317
8.5.2 Planificacin esttica o dinmica .................................................................... 318
8.5.2.1 Planificacin esttica ............................................................................ 319
8.5.2.2 Planificacin dinmica: autoplanificacin (self/chunk
scheduling), autoplanificacin guiada (GSS) y trapezoidal
(trapezoid self scheduling) ........................................................................... 319
xi
NDICE
Captulo
Introduccin
INTRODUCCIN
INTRODUCCIN
El paso que hay que dar es bastante claro: utilizar muchos procesadores,
para repartir la ejecucin de un programa entre ellos; es decir, utilizar
sistemas paralelos. Adems, las tecnologas de fabricacin facilitan esta
posibilidad: construido un procesador (chip), se hacen fcilmente miles de
ellos y de manera relativamente barata. Por tanto, por qu no utilizar 100,
1000, 10 000... procesadores para resolver un problema? Tericamente, y si
supiramos cmo hacerlo, utilizando P procesadores podramos ejecutar un
programa P veces ms rpido. Por desgracia, esto no va a ser as, ya que van
a aparecer importantes problemas nuevos: cmo se reparte el trabajo entre
los procesadores? son independientes los procesos o hay que
sincronizarlos? cmo se implementa la comunicacin entre procesadores?...
Existen muchas maneras de estructurar un computador de P procesadores.
Algunas caractersticas sern comunes en todos ellos, y otras, en cambio, no.
Existen diferentes formas de clasificar estas arquitecturas o estructuras. De
entre ellas, la ms conocida o utilizada es, seguramente, la de Flynn (1966),
quizs por lo simple que es. En esta clasificacin se tienen en cuenta dos
parmetros: el nmero de flujos de instrucciones (es decir, el nmero de PCs
o contadores de programa) y el nmero de flujos de datos que operan
simultneamente. La siguiente figura recoge dicha clasificacin:
flujos de datos
uno
flujos de
instrucciones
muchos
uno
muchos
SISD
SIMD
MIMD
INTRODUCCIN
INTRODUCCIN
Computadores Vectoriales
1.1
QU ES UN COMPUTADOR VECTORIAL?
buc:
FLD
FLD
FADD
FST
F1,A(R1)
F2,B(R1)
F3,F2,F1
C(R1),F3
ADDI R1,R1,#8
SUBI R2,R2,#1
BNZ
R2,buc
longitud = 8
paso = 2
Si el procesador fuera superescalar, quizs se podra conseguir algo ms de una instruccin por ciclo.
1.1
QU ES UN COMPUTADOR VECTORIAL?
LV
LV
ADDV
SV
V1,A(R1)
V2,B(R1)
V3,V1,V2
C(R1),V3
; leer el vector A
; leer el vector B
; sumar ambos vectores
; escribir el resultado en el vector C
BD
AM
...
...
...
BD
AM
...
...
BD L AM M
LV V2,B(R1)
...
BD L AM M
...
BD .
...
BD L AM .
...
...
10
11
12
13
14
15
...
... 14+N
ADDV V3,V1,V2
SV C(R1),V3
1
ti
(N ciclos)
...
(N ciclos)
...
(N ciclos)
...
(Por ahora, supongamos que los operandos que necesitan las instrucciones ADDV y SV se
pueden obtener en los ciclos 8 y 11, tal como se indica en la tabla).
2
Las fases de ejecucin habituales: BD, bsqueda y descodificacin de la instruccin; L, lectura de los
operandos; AM, clculo de la direccin de memoria; A, una operacin en una unidad funcional; M, una
operacin en memoria; E, escritura del resultado en los registros. Cada instruccin utiliza solamente
las fases que necesita para su ejecucin.
10
Las responsables de las dependencias de control son las instrucciones de salto. En general, despus
de la instruccin de direccin i se ejecuta la instruccin de direccin i+1, salvo en el caso de los
saltos. Cuando ejecutamos un salto no sabemos qu instruccin ser la siguiente hasta que el salto
termine, por lo que hay que parar al procesador (aunque existen muchas tcnicas para evitar esos
ciclos "muertos").
1.1
QU ES UN COMPUTADOR VECTORIAL?
11
1.1.1.2
1.1.1.3
Registros vectoriales
12
registros vectoriales
U.F.
1.1.1.4
Programas vectoriales
1.1
QU ES UN COMPUTADOR VECTORIAL?
13
14
Memoria
Registros
Unidades
funcionales
Procesador
escalar
(completo)
Unidad de
direcciones
(datos)
(op.)
Control del
procesador
vectorial
Vi = Vj OP Vk
(OP = ADD, SUB, MUL, DIV...)
1.2
15
DEPENDENCIAS DE DATOS
LV Vi,A(Rj)
SV A(Rj),Vi
MOVI VS,#8
; el paso es 8
LV V1,A(R1)
De esta manera se cargarn en el registro V1 64 elementos de un vector,
correspondientes a las direcciones A+R1, A+R1+8, A+R1+16
En algunos computadores es necesario indicar explcitamente el paso de
los vectores en la propia instruccin, utilizando para ello un registro de
propsito general.
1.2
DEPENDENCIAS DE DATOS
16
BD
BD
L
L
AM
A
M
A
M
E
LV
V1,A(R1)
ADDVI V2,V1,#1
SV
A(R1),V2
BD L AM M M M E ... E
BD . . . . . ... . L A A E ... E
ADDVI V2,V1,#1
SV A(R1),V2
ciclos
1.2
17
DEPENDENCIAS DE DATOS
LV V1,A(R1)
BD L AM M
...
BD .
...
BD L AM .
ADDVI V2,V1,#1
SV A(R1),V2
ciclos
(N cicl.)
...
...
(N cicl.)
...
...
LV
ADDVI
ADDVI
SV
SV
sin encadenamiento: T ~ 3N
con encadenamiento: T ~ N
1.2.1.1
BD L AM M
BD .
10
11
12
13
14
15
BD L AM M
LV V2,B(R1)
ADDV V3,V1,V2
SV C(R1),V3
BD L AM
1
...
...
E
14+N
18
L
comienzo (3)
AM
M
lat. UF (3)
...
dato 1 (6+1)
...
dato N (6+N)
1.2
19
DEPENDENCIAS DE DATOS
inic.
lat. UF dato 1
con encadenamiento
dato N
inic.
lat. UF dato 1
dato N
6+1
6+N
6+1
6+N
ADDVI V2,V1,#1
6+N+1
9+N+1
9+2N
[7]
9+1
9+N
SV A(R1),V2
9+2N+1
13+2N+1 13+3N
[10]
13+1
13+N
LV V1,A(R1)
C = A + B
sin encadenamiento
inic. lat. UF dato 1 dato N
con encadenamiento
inic. lat. UF dato 1 dato N
LV V1,A(R1)
6+1
6+N
6+1
6+N
LV V2,B(R1)
7+1
7+N
7+1
7+N
7+N+1
10+N+1
10+2N
[8]
10+1
10+N
10+2N+1
14+2N+1 14+3N
[11]
14+1
14+N
ADDV V3,V1,V2
SV C(R1),V3
20
1.3
DEPENDENCIAS ESTRUCTURALES
Los buses de memoria pueden usarse tanto para una lectura como para una escritura; en algunas
mquinas, en cambio, los buses estn "dedicados": unos son slo para leer y otros slo para escribir.
Si no puede leerse un registro mientras se est escribiendo, entonces habr que esperar a que finalice
la escritura.
1.3
21
DEPENDENCIAS ESTRUCTURALES
LV V1,A(R1)
ADDVI V2,V1,#1
BD L AM M
M M
E E ...
BD . .
. .
L A
A E E ...
BD L AM .
. .
SV A(R1),V2
(N ciclos)
? .
...
...
(N ciclos)
...
bus ocupado...
...
L M M M E ...
(N cicl.)
libre
o, esquemticamente:
LV
ADDVI
T ~ 2N
SV
A = A + 1
LV V1,A(R1)
ADDVI V2,V1,#1
SV A(R1),V2
un bus / encadenamiento
inic. lat. UF dato 1 dato N
3
6+1
6+N
[7]
9+1
9+N
[6+N]
9+N+1
9+2N
Repitamos el anlisis, pero con el segundo ejemplo que hemos visto antes.
En ambos casos, las instrucciones se encadenan, pero en el primer caso la
mquina cuenta con un solo bus de memoria, y en el otro caso cuenta con
dos buses.
C = A + B
un bus / encadenamiento
inic. lat. UF dato 1 dato N
LV V1,A(R1)
6+1
6+N
6+1
6+N
LV V2,B(R1)
6+N
9+N+1
9+2N
7+1
7+N
ADDV V3,V1,V2
[10+N]
12+N+1
12+2N
[8]
10+1
10+N
SV C(R1),V3
[9+2N]
12+2N+1 12+3N
[6+N]
9+N+1
9+2N
22
LV
LV
ADDV
LV
ADDV
SV
un bus / encadenamiento: 3N
SV
2.
A = A + 1
(N = 64)
sin encadenamiento
encadenamiento / 1 bus
encadenamiento / 2+ buses
13 + 3N = 205 ciclos
9 + 2N = 137 ciclos
13 + N = 77 ciclos
C = A + B
(N = 64)
sin encadenamiento / 1 bus
sin encadenamiento / 3 buses
encadenamiento / 1 bus
encadenamiento / 2 buses
encadenamiento / 3 buses
16 + 4N = 272 ciclos
14 + 3N = 206 ciclos
12 + 3N = 204 ciclos
9 + 2N = 137 ciclos
14 + N = 78 ciclos
3,20 ciclos/dato
2,14 c/d
1,20 c/d
4,25 c/d
3,22 c/d
3,19 c/d
2,14 c/d
1,22 c/d
1.3
23
DEPENDENCIAS ESTRUCTURALES
m1
A1
A5
A9
A13
m2
A2
A6
A10
m3
A3
A7
A11
...
tiempo (ciclos)
m0
m1
m2
m3
...
...
24
nm t m
De esa manera, cuando hay que reutilizar un determinado mdulo ya han
pasado al menos nm ciclos, y por tanto estar libre.
Para el caso general, s > 1, hay que calcular cuntos mdulos se utilizan
en una determinada operacin. Por ejemplo, en el caso anterior, cuando s =
4, slo se utiliza un mdulo de memoria, siempre el mismo (m0). Puede
demostrarse fcilmente que el nmero de mdulos que se utilizan en una
operacin de memoria es:
nm
MCD(nm, s )
nm
tm
MCD(nm, s )
Analizando la expresin anterior. se observa que la mejor situacin se
corresponde con el caso MCD(nm,s) = 1, es decir cuando, nm y s son primos
entre s, ya que se utilizan todos los mdulos de memoria. En los casos ms
habituales, nm es una potencia de 2 (8, 16, 32, 64...). En esos casos, y si no
hay conflicto cuando s = 1, no habr conflictos para cualquier vector de paso
impar (1, 3, 5...), pero podra haberlos para los casos de s par.
Existe una situacin ptima. Si el nmero de mdulos de memoria, nm, es
un nmero primo, entonces cualquier paso s ser primo con l (salvo sus
mltiplos). Por ejemplo, si nm = 5, no hay problemas con los vectores de
1.3
25
DEPENDENCIAS ESTRUCTURALES
sf = 1
sc = 4
sD = 5
sd = 3
6
m1
A01
A11
A21
A31
m2
A02
A12
A22
A32
m3
A03
A13
A23
A33
sin conflictos
conflictos (todos en m0)
sin conflictos
sin conflictos
m0
A00
A13
A22
A31
sf = 1
sc = 5
sD = 6
sd = 4
m1
A01
A10
A23
A32
m2
A02
A11
A20
A33
m3
A03
A12
A21
A30
-
sin conflictos
sin conflictos
conflictos
conflictos
Como hemos comentado, el ideal sera que nm fuera un nmero primo. Por ejemplo, si nm fuera 5,
los cuatro vectores del ejemplo (f, c, D y d) podran accederse sin problemas si se dejan los
correspondientes huecos (lo dejamos como ejercicio para el lector).
26
1.3.2.2
A = A + 1
LV V1,A(R1)
6+1
6+N
ADDVI V2,V1,#1
[7]
9+1
9+N
SV A(R1),V2
[10]
m0
m1
m2
m3
m4
m5
m6
M
M
M
M
M
m7
M
M
M
M
M
M
M
M
M
10
M
M
M
11
12
13
14
15
16
17
18
M
-
M
M
M
M
M
m
M
M
M
m
m
M
M
M
m
m
M
M
M
M
M
M
M
M
19
M
M
M
1.3
DEPENDENCIAS ESTRUCTURALES
27
28
inic.
mod. ocup.
t. esp.
lat. UF
dato 1
dato N
6+1
6+N
[7]
9+1
9+N
[10] ??
5 / 6 7 0 / 1
+4
17+1
17+N
En general, para calcular el nmero de ciclos que hay que esperar para
utilizar la memoria, hay que hacer el anlisis con todas las instrucciones que
estn en memoria, ya que cada una de ellas ocupar tm mdulos de memoria.
Como consecuencia de ello, no se pueden permitir ms de nm div tm
operaciones de memoria simultneamente, ya que con ese nmero de
instrucciones se ocupan todos los mdulos de memoria. Por ejemplo, para el
anterior caso (nm = 8 y tm = 3) no se pueden procesar simultneamente ms
de 8 div 3 = 2; estara de sobra, por tanto, un hipottico tercer bus a
memoria.
1.3
29
DEPENDENCIAS ESTRUCTURALES
do i = 0, N-1
A(i) = A(i) + 1
enddo
MOVI
MOVI
mas: MOV
VS,#1
R1,#N
VL,R1
LV
V1,A(R2)
ADDVI V2,V1,#1
SV
A(R2),V2
ADDI
SUBI
BGTZ
R2,R2,#Lmax
R1,R1,#Lmax
R1,mas
( tam. pal.)
30
TV = 30 + 3N
pero
<
Lmax = 64
1.4
tbuc = 10 ciclos
1.4
31
R y N1/2
TE = te N
en modo vectorial 7
TV = ti + tv N
ti = tiempo de inicio
tv = tiempo para procesar un elemento del vector
TV
250
200
pendiente = tb
150
2ti
100
TV = 30 + 2N
5
ti
0
N1/2
0
25
50
75
100
125
150
N
N
=
TV ti + tv N
32
N
N
=
OpCF F Mflop/s
TV ti + tv N
R/2
(rendimiento)
N1/2
N (nmero de elementos)
R = lim N RN =
1
OpCF F
tv
en el intervalo [0, 1]
N1/2 = ti / tv
(entero superior)
En lo que a la velocidad de clculo respecta, no es lo mismo efectuar una suma con los vectores que
efectuar dos sumas y una multiplicacin.
1.4
33
1.4.1.2
t N
TE
= e
T V ti + t v N
K =
te
tv
Si se prefiere, el tiempo de ejecucin y la velocidad de clculo pueden darse en funcin de los dos
parmetros que acabamos de definir, N1/2 y R:
TV = (N + N1/2) / R
RV = R (1 / (1 + N1/2/N))
34
1.4.1.3
NV
Nv =
ti
N1/ 2
=
te tv K 1
Por tanto, si los vectores a procesar son ms cortos que Nv (funcin de N1/2
y K), entonces no merece la pena ejecutar en modo vectorial, ya que la
ejecucin en modo escalar ser ms rpida.
TE
TE
=
=
TVE
fTV + (1 f )TE
TE
f
TE
+ (1 f )TE
K
K
f (1 K ) + K
1.4
35
KV =
4
2
f1 / 2 = 1
1
KV 1
36
N
N
N
N
=
=
=
TVE
fTV + (1 f )TE
f (ti + tv N ) + (1 f )te N
f (ti + tv N ) + (1 f ) K tv N
Como siempre, para ponerlo en Mflop/s hay que multiplicar por el nmero
de operaciones en coma flotante realizadas, y por la frecuencia de reloj (si el
tiempo estaba en ciclos).
En algunos textos, la expresin anterior suele darse de la siguiente manera:
RN,f = R N f
donde N = 1 / [1 + N1/2/N]
f = 1 / [f + (1f) K N]
es decir, hay un rendimiento mximo R,1 cuando la longitud de los vectores es infinita y
el factor de vectorizacin es 1; y luego existen dos limitaciones, una debida a la longitud finita
de los vectores, N, y otra debida a que el factor de vectorizacin es f y no 1.
Pongamos un ejemplo. Un computador vectorial tiene los siguientes parmetros: R = 800
Mflop/s, N1/2 = 60, K = 10, f = 0,8 y N = 128.
Si fueran N infinito y f = 1, se obtendran 800 Mflop/s. Como N = 128, el primer lmite es N =
0,68. Adems, como f = 0,8 (y N = 128) tenemos un segundo lmite, f = 0,46. En
consecuencia, la velocidad de clculo que se consiga ser: 800 0,68 0,46 = 252 Mflop/s.
16
Ley de Amdahl
14
12
tv = 5 ns
te = 66,6 ns
10
8
6
tv = 10 ns
te = 33,3 ns
CRAY X-MP
tv = 10 ns
te = 66,6ns
2
0
0
0.2
0.4
0.6
0.8
f (factor de vectorizacin)
1.5
37
1.5
38
una
las
hay
tres
A = B + C
2:
D = A
1
A
A = B + C
2:
B = D
1.5
39
A = B + C
2:
A = D
do i = 2, N-2
1: A(i) = B(i) + 2
2: C(i) = A(i-2) + A(i+1)
enddo
A, 2
A, 2
A, 1
i=0
i=1
i=2
A, 1
do i = 2,
do j = 1,
1: A(i,j)
2: C(i,j)
enddo
enddo
N-1
N-2
= A(i,j-1) * 2
= A(i-2,j+1) + 1
A, (0, 1)
A, (0, 1)
A, (2, 1)
A, (2, 1)
2
grafo de dependencias
espacio de iteraciones
40
1.5.2 Vectorizacin
1.5.2.1 Vectores de una dimensin
Antes de formalizar las tcnicas de vectorizacin, veamos algunos
ejemplos 10.
1.5.2.1.1 Primer ejemplo
do i = 0, N-1
A(i) = B(i) + C(i)
enddo
VL,#N
VS,#1
LV
LV
ADDV
SV
V1,B(R1)
V2,C(R1)
V3,V1,V2
A(R1),V3
10 Salvo que se indique lo contrario, los vectores son de tamao N (o NN); la direccin A indica el
primer elemento del vector, A0; A+1 indica el siguiente elemento, etc. (sin considerar el tamao de
los elementos y la unidad de direccionamiento de la memoria). Vectores de nombre diferente utilizan
posiciones de memoria diferentes, es decir, no se solapan (no hay aliasing). El contenido inicial del
registro utilizado para direccionar es siempre 0 (en el ejemplo, R1).
1.5
41
do i = 0, N-1
1: A(i) = B(i) + C(i)
2: D(i) = A(i)
enddo
A, 0
A, 0
2
grafo de dependencias
espacio de iteraciones
(2)
LV
LV
ADDV
SV
V1,B(R1)
V2,C(R1)
V3,V1,V2
A(R1),V3
;A = B + C
SV
D(R1),V3
42
1
A, 1
A, 1
1 < 2
(2)
LV
LV
ADDV
SV
V1,B+1(R1)
V2,C+1(R1)
V3,V1,V2
A+1(R1),V3
LV
SV
V4,A(R1)
D+1(R1),V4
do i = 0, N-2
1: A(i) = B(i) + C(i)
2: D(i) = A(i+1)
enddo
i
A, 1
A, 1
1.5
43
LV
SV
V1,A+1(R1)
D(R1),V1
(1)
LV
LV
ADDV
SV
V2,B(R1)
V3,C(R1)
V4,V2,V3
A(R1),V4
do i = 1, N-1
1: A(i) = B(i-1) + 1
2: B(i) = A(i)
enddo
1
A, 0
A, 0
B, 1
B, 1
A, 3
44
Vectores de N dimensiones
1.5.2.2
; nmero de filas
; longitud de las filas
; paso
V1,B(R1)
V2,C(R1)
V3,V1,V2
A(R1),V3
ADDI R1,R1,#M
SUBI R2,R2,#1
BNZ R2,buc
s=1
0,0
0,1
0,M-1
1,0
1,1
1,M-1
N-1,M-1
i
; siguiente fila
; una fila menos
N-1,0 N-1,1
1.5
45
R2,#M
VL,#N
VS,#M
buc: LV
LV
ADDV
SV
V1,B(R1)
V2,C(R1)
V3,V1,V2
A(R1),V3
ADDI
SUBI
BNZ
R1,R1,#1
R2,R2,#1
R2,buc
; nmero de columnas
; longitud de las columnas
; paso
A
s=M
0,0
0,1
0,M-1
1,0
1,1
1,M-1
N-1,M-1
i
; siguiente columna
; una columna menos
N-1,0 N-1,1
1.5.2.3
11 En estos ejemplos hemos supuesto que las matrices estn almacenada en memoria por filas, tal como,
por ejemplo, se hace en C; en Fortran, en cambio, las matrices se guardan por columnas.
46
do i = 1, N-1
A(i) = B(i)
B(i) = B(i-1)
enddo
B, 0
V1,B+1(R1)
A+1(R1),V1
MOVI R3,#N-1
B, 1
1.5.2.4
LV
SV
buc:
FLD
FST
ADDI
SUBI
BNZ
F1,B(R2)
B+1(R2),F1
R2,R2,#1
R3,R3,#1
R3,buc
Test de dependencias
1.5
47
a i1 + b = c i2 + d
es decir, hay que saber si existen dos valores i1 e i2, dentro de los lmites de
iteracin del bucle, para los que coincidan las direcciones de acceso al
vector.
ai+b
ci+d
L1 i1
i2
L2
48
L1
L2
L1
(1)
L2
(2)
L1
L2
(3)
do i = 1, 100
A(2*i) = ...
... = A(2*i+1)
enddo
(1 0) / MCD(2, 2) = 1/2
Por tanto, no hay dependencias entre las dos instrucciones; en este caso,
una instruccin escribe elementos pares y la otra lee elementos impares.
12 Habr que tener en cuenta los pasos de los vectores (a y c) y la longitud del segmento que se solapa,
para comprobar si ambos accesos coinciden en, al menos, un elemento del vector.
1.5
(2)
do i = 5, 100
A(i-5) = ...
... = A(2*i+90)
enddo
49
Por tanto, puede haber una dependencia. Pero no la hay, porque los
intervalos de acceso son disjuntos:
wr:
rd:
(3)
do i = 1, 100
A(3*i+100) = ...
... = A(2*i-1)
enddo
Podra haber una dependencia; los intervalos de acceso son los siguientes:
wr:
rd:
Los dos intervalos tienen un trozo en comn, por lo que puede haber una
dependencia; y en este caso la hay: por ejemplo, la escritura de la
iteracin i = 1 en (A103) se lee en la iteracin i = 52.
(4)
do i = 1, 100
A(6*i+3) = ...
... = A(3*i+81)
enddo
(81 3) / MCD(6, 3) = 26
Por tanto, puede haber una dependencia. Los intervalos de acceso son los
siguientes:
wr:
rd:
A9 ...
... A603
A84 ... ... A381
do k = 1, 50, 1
A(2*k-1) = ...
B(4*k+3) = ...
enddo
50
1.5.3 Optimizaciones
El proceso de compilacin es esencial en la obtencin de altas velocidades
de clculo en un computador vectorial. No hay que olvidar que de no obtener
un factor de vectorizacin elevado el rendimiento de la mquina ser
bastante bajo (ley de Amdahl). Acabamos de ver cul es la condicin que
hay que cumplir para poder vectorizar un bucle: que no haya ciclos de
dependencias. En todo caso, algunas de las dependencias que aparecen en los
bucles no son intrnsecas a la operacin que se realiza, sino que estn
relacionadas con la manera en que se indica dicha operacin (por ejemplo,
las antidependencias o las dependencias de salida). En esos casos, es posible
efectuar pequeas transformaciones del cdigo original que facilitan la
vectorizacin final. Vamos a ver dos tipos de optimizaciones: las que ayudan
a que desaparezcan las dependencias, y las que ayudan a obtener una mayor
velocidad de clculo.
1.5.3.1
1.5
51
Las dos definiciones, NP1 y NP2, que se han hecho antes del bucle son un
obstculo para poder tomar una decisin. Por ello, antes que nada, el
compilador deshar ambas definiciones en todo el programa, sustituyendo
las variables por su valor original (una constante), y entonces har el anlisis
de dependencias. Recuerda: si no puede analizar los ndices de los vectores,
el compilador debe asumir que s existe la dependencia.
do i = 1, L
1: B(i) = A(L+1) + C(i)
2: A(i) = A(i) - 1
do j = 1, L
3:
D(j,L+1) = D(j-1,L+2) * C(j) + 1
enddo
enddo
2
12
5
3
17
8
4
22
11
5
27
14
...
...
...
52
k=3i1
Las variables que forman una serie aritmtica en funcin del ndice del
bucle se conocen como variables de induccin. Eliminando las variables de
induccin, el bucle anterior puede escribirse as:
do i = 1, L
R(3*i-1) = R(5*i+2) + 1
enddo
1
A, 0
A, 1
1.5
53
do i = 0, N-2
0: [T(i)] = A(i+1)
1: A(i) = B(i) + C(i)
2: D(i) = A(i) + [T(i)]
enddo
A, 1
T, 0
A, 0
1.5.3.4
(2/0)
(1)
LV
LV
LV
ADDV
SV
V1,A+1(R1)
V2,B(R1)
V3,C(R1)
V4,V2,V3
A(R1),V4
(2)
ADDV V5,V1,V4
SV
D(R1),V5
do i = 0, N-3
1: A(i) = B(i) + C(i)
2: A(i+2) = A(i) * D(i)
enddo
1
A, 0
A,2
54
do i = 0, N-3
1: [T(i)] = B(i) + C(i)
2: A(i+2) = [T(i)] * D(i)
3: A(i) = [T(i)]
enddo
T, 0
T, 0
A, 2
1.5.3.5
(1)
LV
V1,B(R1)
LV
V2,C(R1)
ADDV V3,V1,V2
(2)
LV
V4,D(R1)
MULV V5,V3,V4
SV
A+2(R1),V5
(1/3)
SV
A(R1),V3
; escritura de la instruccin 1
do i = 0, N-1
do j = 1, N-1
A(i,j) = A(i,j-1) + 1
enddo
enddo
1
A, (0, 1)
1.5
55
Basta con utilizar como vector las columnas de la matriz (s = N), es decir,
intercambiar el orden original de los bucles.
El intercambio de bucles no puede aplicarse a cualquier bucle, ya que, por
supuesto, hay que respetar las dependencias entre instrucciones. Por
ejemplo, no puede aplicarse en el siguiente ejemplo: no se puede procesar la
matriz por columnas, puesto que en la columna j se necesitan los resultados
de la columna j+1.
j
do i = 1, N-1
do j = 1, N-2
(1) A(i,j) = B(i-1,j+1) + 1
(2) B(i,j) = A(i,j-1)
enddo
enddo
1
A, (0, 1)
2
B, (1, -1)
56
do i = 1, N-1
do j = 1, N-1
(1) A(i,j) = A(i-1,j) + 1
(2) B(i,j) = B(i,j-1) * 2
enddo
enddo
A, (1, 0)
i
B
A
2
B, (0, 1)
1.5.3.6
1.5
57
1.5.3.7
Con esta optimizacin se intenta fundir dos (o ms) bucles en uno solo,
para intentar reducir toda la sobrecarga asociada al control del bucle, y para,
si es posible, reutilizar los resultados almacenados en los registros. Por
ejemplo,
do i = 0, N-1
Z(i) = X(i) + Y(i)
enddo
do i = 0, N-1
R(i) = Z(i) + 1
enddo
do i = 0, N-1
Z(i) = X(i) + Y(i)
R(i) = Z(i) + 1
enddo
58
1.5.3.8
1, L
= X(i) + Y(i)
1, L
= Z(i+1) + 1
do i = 1, L
Z(i) = X(i) + Y(i)
R(i) = Z(i+1) + 1
enddo
do i = 0, 9
do j = 0, 9
A(i,j) = A(i,j) + 1
enddo
enddo
do i = 0, 99
A(i) = A(i) + 1
enddo
1.5
59
1.5.3.9
Otras optimizaciones
60
1.5.4.1
Uso de mscaras
V1,V2
SxxVS V1,F1
CVM
POP
R1,VM
1.5
MOVI
MOVI
MOVI
61
VL,#N
VS,#1
F1,#5
LV
V1,B(R1)
SGTVS V1,F1
LV
V2,A(R1)
ADDVI V3,V2,#1
SV
A(R1),V3
CVM
1.5.4.2
Vectores de ndices
4
1
62
V1,A(V2)
SVI
A(V2),V1
CVI
V1,R1
1.5
63
VL,#M
R1,#1
V4,R1
V5,V4,V4
LVI
V1,B(V5)
ADDVI V2,V1,#1
SVI
A(V5),V2
; 0, 1, 2, 3...
; registro de ndices: i*i
; direccionamiento indexado
Para indicar los ndices hemos utilizado el registro V5, en el que hemos
cargado previamente los resultados de la funcin i*i. Despus, hemos
utilizado el modo de direccionamiento indexado (base + vector de ndices)
para acceder al vector.
El modo de direccionamiento indexado puede utilizarse tambin, por
ejemplo, para ejecutar el bucle del apartado anterior if (B(i)>5)
then A(i) = A(i) + 1 de la siguiente manera:
MOVI
MOVI
VL,#N
VS,#1
MOVI
F1,#5
LV
V1,B(R1)
SGTVS V1,F1
MOVI
CVI
POP
MOV
CVM
R2,#1
V2,R2
R1,VM
VL,R1
LVI
V3,A(V2)
ADDVI V4,V3,#1
SVI
A(V2),V4
64
1.6
RESUMEN
1.6
RESUMEN
65
como indica la ley de Amdahl, el rendimiento final del sistema ser muy
bajo. Como siempre, para facilitar la tarea del compilador y mejorar su
rendimiento, la ayuda de un usuario experto es siempre importante. Algunas
de las tcnicas de vectorizacin son ya clsicas y las aplican todos los
compiladores. Esas estrategias se basan en el anlisis de las dependencias
entre instrucciones, y son comunes a los compiladores que intentan
paralelizar el cdigo para ser ejecutado en sistemas con ms de un
procesador. Por ello, las volveremos a analizar en un tema posterior.
66
1.6
RESUMEN
67
Todas las mquinas citadas han sido siempre las ms rpidas del
momento, pero tambin, con diferencia, las ms caras. La evolucin de los
microprocesadores en los ltimos aos, junto con el uso del paralelismo, ha
ido arrinconando a este tipo de arquitecturas, con lo que, en un futuro
cercano, parece que jugarn un papel cada vez menor en el campo del
clculo cientfico. Para ello, habr que aprender a programar y utilizar los
sistemas de muchos procesadores de manera eficiente, para aprovechar su
gran potencial de clculo. En todo caso, es habitual que los procesadores
(super)escalares actuales dispongan de instrucciones de tipo vectorial
(SIMD) que, por ejemplo, dividen los 64 bits de una palabra en 8 palabras de
8 bits que son tratadas como un vector corto, y con las que se realizan
operaciones tipo producto/suma encadenadas.
Hoy en da, los procesadores vectoriales aparecen como nodos
especializados de un sistema paralelo ms general. En ese tipo de sistemas,
MPP (massive parallel processors) hay que buscar el futuro del clculo
paralelo: miles de procesadores colaboran en la resolucin de un problema y
se comunican entre ellos mediante una red de comunicacin de gran
velocidad. En dicha red, algunos procesadores estn especializados en
determinado tipo de clculo, por ejemplo, clculo vectorial.
Siempre es posible, en todo caso, encontrarse con sorpresas en la
evolucin de los computadores. En el top500 de junio de 2002 (lista de las
500 mquinas ms rpidas del mundo, que se publica dos veces al ao), se
produjo un cambio significativo. En contra de la lnea seguida en los ltimos
aos, el nmero 1 de la lista fue un (multi)computador vectorial: Earth
Simulator. Se trataba de un computador japons de propsito especfico con
5120 procesadores vectoriales. Utilizaba chips NEC SX-6, que contienen
cada uno 8 procesadores vectoriales. Lograba una velocidad de Rmax = 36
Tflop/s (el segundo en dicha lista, junio 2002, el ASCI White, alcanzaba 7,2
TF/s, utilizando 8192 procesadores). En la lista citada (junio 2002) haba 41
computadores vectoriales.
En 2009 disponemos de una nueva versin de dicha mquina (1280
procesadores NEC SX-9, de 350 millones de transistores, a 3,2 GHz) que ha
logrado una velocidad de clculo de 122,4 TF/s. Cada CPU dispone de una
unidad superescalar (de 4 vas) y una unidad vectorial con las siguientes
caractersticas: 72 registros vectoriales de 256 elementos y 8 conjuntos o
pipes de unidades funcionales vectoriales (+, , /, lgicas, mscaras y
LV/SV). Cada chip puede alcanzar los 102,4 GF/s.
68
Computadores Paralelos
(conceptos bsicos)
2.1
INTRODUCCIN
70
2.2
71
COMPUTADORES DM-SIMD
2.2
COMPUTADORES DM-SIMD
Computador
front-end
Procesador
de control
Pr + M + I/O
Array de clculo
72
2.3
73
COMPUTADORES MIMD
2.3
COMPUTADORES MIMD
P0
P1
Pp1
Red de comunicacin
M0
Mm1
Memoria principal
sistema
E/S
74
P0
Pp1
E/S
E/S
K
Red de comunicacin
2.3
COMPUTADORES MIMD
75
76
2.4
ALGUNOS PROBLEMAS
2.4
77
ALGUNOS PROBLEMAS
78
la comunicacin
ello, la red de
o MPP). En un
programa puede
Tp = Tej + Tcom
donde Tej representa el tiempo de ejecucin real y Tcom el de
comunicacin. El tiempo de ejecucin se reduce (en teora) con el
nmero de procesadores, pero el de comunicacin en cambio, crece.
La siguiente figura muestra una simplificacin de ese compartimiento.
Tp
Tcom
Tej
Nm. procesadores
2.5
79
2.5
(habitualmente en %)
80
f
i =1
Ts
)
i
2.5
81
(1f) Ts
f Ts
1 procesador
problema de mayor tamao
f Ts P
(1f) Ts
en paralelo
P procesadores
(1f) Ts
f Ts / P
en paralelo
(1f) Ts
f Ts
82
fa = Ts / Tp = (1f) + f P
3.1
84
3.1
85
86
3.1
87
No hay que olvidar, sin embargo, que el control del contenido de la cache,
y el de la coherencia en concreto, se hace por bloques, no palabra a palabra:
se cargan bloques de datos, se borran bloques, se anulan bloque, etc. Por
ello, es posible que un bloque de datos se encuentre en ms de un
procesador, aunque todas las variables del bloque sean privadas. Por
ejemplo:
Bloque de datos de 4 palabras
X
Variables del
procesador Pi
Variables del
procesador Pj
Aunque las variables son privadas estn en el mismo bloque de datos, por
lo que el bloque ser compartido y tomar parte en las operaciones de
coherencia. Se dice que hay un problema de falsa comparticin (false
sharing). Para evitar este efecto es necesario distribuir los datos en memoria
de manera adecuada y es til que los bloques de datos no sean muy grandes.
88
3.2
3.2
89
P1
MC1
A = 43
P2
P1
wr A,#3
wr A,#3
A=4
MC2
MC1
MP
A = 43?
Invalidacin
A = 43
A = 43
INV A
MC2
BC A,3
MP
A = 43?
Actualizacin
90
para los bloques. Un autmata finito (el snoopy) se encargar en cada cache
de ir modificando los estados de los bloques en funcin de las operaciones
que se realicen, tanto desde el procesador local como desde el resto de los
procesadores, sobre los mismos.
3.2
91
modificado
(dirty)
compartido
(shared)
Estado
I
E
S
M
O
Como hemos comentado al principio, los dos primeros bits son los
mismos que se utilizan en los sistemas de un solo procesador, por lo que, dfe
momento, slo se aade un bit ms al directorio.
Una mquina de estados finitos en cada procesador, el snoopy, se encarga
de mantener los estados de los bloques de datos en la cache de acuerdo a la
definicin anterior, para lo que hay que tomar en consideracin las
siguientes acciones:
1. Acciones del procesador local
PR: processor read
Se lee una variable (en un bloque de datos). Si el bloque est en
la cache (acierto), no hay que hacer nada; pero si no est (fallo)
hay que generar una peticin de lectura de ese bloque (BR, bus
request).
PW: processor write
Se escribe en una variable (un bloque de cache). En general, hay
que avisar a los otros procesadores, para que actualicen el estado
de dicho bloque en su cache: INV (invalidar) o BC (actualizar),
en funcin del tipo de protocolo. Adems, si ha sido un fallo, hay
que pedir el bloque de datos correspondiente.
92
3.2
93
94
3.2.2.1
(Silicon Graphics)
acierto
fallo
Estado
presente
PR
I, -
S
M
PW
BR
BR
BR,INV
INV
S
S
Trfico (datos)
MP MC:
MC MP:
//
//
BR
BW
INV
I
BW
BW
I S, M
M S, I (+reemplazo)
M
BR (BW)
PR - BR
INV (BW)
PW (INV)
S
INV
PW (BR,INV)
PR (BR)
I, -
3.2
95
18 El estado S no implica que necesariamente tenga que haber ms copias en el sistema; es decir,
aunque es seguro que en algn momento s ha habido ms de una copia, pueden haber sido
reemplazadas todas ellas, quedando una sola copia, en estado S. Adems, en este protocolo la primera
copia tambin se carga en estado S, ya que no se utiliza el estado E (una sola copia).
96
through, es posible que el bloque que hay que borrar est en estado M, en
cuyo caso habr que actualizar su contenido en MP.
Trfico en el bus compartido
El trfico que se genera en el bus que conecta los procesadores y la
memoria en un multiprocesador es un aspecto crtico en el rendimiento del
sistema. Dado que es un recurso compartido, el bus puede saturarse; en ese
caso, la latencia de las comunicaciones con memoria crecer, y la velocidad
de clculo bajar. Por ello, un protocolo de coherencia adecuado debe
intentar reducir dicho trfico, para que se pueda conectar el mayor nmero
de procesadores al bus.
En la parte inferior de la tabla de transiciones de estados del protocolo se
muestra el trfico en el bus de datos. Hay que transferir un bloque de datos
en estos dos casos: de memoria principal a memoria cache al generarse la
seal BR (es decir, cuando un bloque pasa de estado I a S o M); y de
memoria cache a memoria principal cuando se genera la seal BW (cuando
un bloque en estado M pasa a estado S, se anula o se reemplaza).
De dnde se traen los bloques de datos?
Cuando hay que cargar un bloque en la cache, normalmente se traer de
MP. Sin embargo, en algunos casos ese bloque se puede traer de alguna otra
cache (porque hay una copia del mismo). Esta posibilidad no disminuye el
trfico en el bus, pero s el tiempo de acceso, porque traerlo desde otra cache
va a ser ms rpido. En cualquier caso, hacer esto genera una interferencia
en el funcionamiento de otro procesador (mientras se est realizando la copia
de cache a cache, no podr utilizar su memoria cache), adems de necesitar
un arbitraje para escoger una determinada copia, por lo que habitualmente se
trae el bloque de MP.
Si el bloque que se quiere traer est en estado M en otra cache, el snoopy
tiene que conseguir esa copia, ya que la MP no est actualizada. Como en el
caso anterior, tenemos dos opciones: actualizar primero la MP, y luego leer
ah el bloque; o copiar el bloque en la cache que lo necesita a la vez que se
est actualizando la MP (por tanto, el bloque est en el bus):
(a)
3.2
97
3.2.2.2
acierto
fallo
Estado
presente
I, -
PR
nsh: E
sh:
PW
BR
Trfico (datos)
MP MC:
MC MP:
BR
INV
BR,INV
INV
BR
BW
//
//
BW
I E, S, M
M S, I (+reemplazo)
BW
98
PR - PW
M
INV (BW)
BR (BW)
PW
PW (INV)
PR - BR
PR
BR
sh
nsh
INV
PW (BR,INV)
INV
PR (BR)
I, -
3.2
99
3.2.2.3
acierto
fallo
Estado
presente
PR
I, -
PW
BR
BR
BR,INV
INV
INV
Trfico (datos)
MP / MC MC:
MC MP:
BR
BW
INV
BW
BW
I S, M
M, O I (+reemplazo)
//
//
PW (INV)
PR - BR
PR - PW
O
BR
INV (BW)
INV (BW)
PW (INV)
PR - BR
S
INV
PW (BR,INV)
PR (BR)
100
3.2.2.4
3.2
101
3.2.3.1
102
compartidos. Esto es, cuando slo hay una copia de un bloque, en las
escrituras no se actualiza la memoria principal; en cambio, cuando hay
varias copias del bloque, todas las escrituras actualizan tambin la memoria
principal. Como el protocolo distingue entre los estados E y S, el bus de
control cuenta con la seal sh (shared): sh = 1 hay copias de dicho
bloque en alguna otra cache; sh = 0 no hay copias.
Las transiciones entre estados y las seales de control de este protocolo se
muestran en la siguiente tabla y en el grafo correspondiente:
Estado siguiente / Seales de control
acierto
fallo
Estado
presente
PR
nsh: E
sh:
PW
nsh:
BR
sh:
BR
BR
M
S BR,BC
M
nsh:
sh:
BC
E
S
BC
S
BW
Trfico (datos)
MP / MC MC:
MC MP:
MC MC*MP*:
BW
(I) E, S, M
M S (+reemplazo)
(I) S(wr); S E, S(wr)
//
//
//
BR
BW
BC
PR - PW
nsh
BR (BW)
PW (BR)
(-)
sh
(BC)
PW
PW (BC)
PR
sh
E
BR
nsh
PW (BC) nsh
PR
BR - BC
sh
PR (BR)
(-)
3.2
103
ambos estados, que indican que slo hay una copia del bloque de datos, se
les aplica la poltica de escritura write-back. En cambio, si se detecta que hay
una o ms copias del bloque en el sistema (sh), el estado del nuevo bloque
ser S, y la posterior poltica de escritura ser write-through, que mantiene
coherentes la memoria principal y las memorias cache.
Del mismo modo, si se escribe sobre un bloque que est en estado S, se
elegir entre E o S en funcin de la seal sh. Ten en cuenta que aunque el
bloque est en estado S (compartido), puede ser que en ese momento sea la
nica copia si se han reemplazado las dems; aprovechamos as la escritura
para actualizar el estado (aunque slo quede una copia, el estado ser E y no
M, porque la poltica de escritura con las copias compartidas es siempre la
misma: hay que actualizar la memoria principal).
Desde el punto de vista del trfico, el caso ms interesante es la transicin
(I, -) S. Si es consecuencia de una lectura, entonces hay que traer el
bloque a la cache, bien desde MP o bien desde otra cache. Si el resto de las
copias son coherentes (E, S), normalmente se traer de MP; si no son
coherentes (M), entonces antes de traer el bloque (o a la vez) habr que
actualizar la memoria principal. Por otro lado, en las transiciones (I, -) S,
cuando son consecuencia de una escritura, adems de traer el bloque hay que
actualizar la memoria principal y todas las copias del mismo. Por tanto,
cuando se genera la seal BC tambin hay que actualizar (una palabra) la
memoria principal (es decir, cumple la misma funcin que la seal BW* que
definimos anteriormente). Por ello, para reducir el trfico de actualizacin,
en el caso escritura/fallo antes de generar la seal BC se espera a obtener la
respuesta de la seal sh; si no, podramos genera la seal BC desde el
comienzo de la operacin.
3.2.3.2
104
acierto
fallo
Estado
presente
PR
E
S
nsh:
sh:
PW
nsh:
BR
sh:
BR
BR
M
O BR,BC
M
nsh:
sh:
BC
M
O
M
nsh:
sh:
BC
M
O
BC
Trfico (datos)
MP / MC MC:
MC MC*:
[ MC MP:
(I) E, S, M, O
(I), S, O(wr) O
M, O (I) ]
BR
//
BC
//
reempl. //
(-)
nsh
PW (BR)
sh
(BC)
nsh
PW
PR - PW
M
BC
BC
(BC)
nsh
PW
PR
PW sh (BC)
PR - BR
BR
sh
PW
BR
nsh
PR
BR - BC
sh
PR (BR)
(-)
3.3
105
3.3
SNOOPY
3.3.1 Problemas
Para mantener la coherencia de datos en un multiprocesador basado en un
bus es suficiente un sistema de tipo snoopy. Los autmatas que hemos
analizado (o variaciones de los mismos) son los que se utilizan en todos los
multiprocesadores. La lgica que tienen que ejecutar los controladores de
coherencia es bastante simple, tanto en el caso de invalidacin como en el de
actualizacin. Pero la implementacin distribuida de esa lgica da lugar a
nuevos problemas, que hacen que no sea inmediato conseguir dispositivos
sencillos, eficientes y correctos. Por supuesto, el snoopy debe funcionar
correctamente en cualquier situacin, ya que de no ser as no podremos
asegurar la coherencia de los datos y, por tanto, disponer de sistemas
paralelos eficientes de memoria compartida.
Un snoopy es un autmata distribuido que se ejecuta en P procesadores.
Esto es lo que produce problemas, ya que hay que coordinar el
funcionamiento de todos los controladores para, al final, obtener el resultado
correcto. Dentro de los problemas que aparecen, la falta de atomicidad es,
probablemente, el ms importante: la necesidad de asegurar que no se
mezclarn, en el tiempo, operaciones de coherencia de dos (o ms)
procesadores sobre un mismo bloque, produciendo resultados incorrectos.
Para mostrar los problemas y las soluciones, analicemos cmo se organiza
un controlador de coherencia para un caso real. En la figura se muestra el
esquema de un controlador de coherencia (simplificado). Analicemos sus
componentes principales.
106
P
data
addr
contr
MC
tags +
state
Bus side
controller
proc.
snoopy
compar.
tag
compar.
state
Cmd
tags +
state
Processor
side
controller
to controller
Write-back buffer
to controller
Data buffer
Addr
Addr
Cmd
system bus
3.3.1.1
3.3
107
3.3.1.2
Bferes de escritura
108
3.3.1.3
Cuando un procesador pone una peticin en el bus, por ejemplo BR, debe
esperar a la respuesta de los dems snoopy, por si existe alguna copia de ese
bloque en otra cache: se debe traer el bloque de memoria, o hay que traerlo
de otra cache, que lo ha modificado? En ese caso, cunto tiempo hay que
esperar hasta estar seguro de que todos han respondido? Las estrategias ms
utilizadas para controlar el tiempo de espera son las siguientes:
Esperar un tiempo fijo preestablecido, hasta estar seguros de que todos
los snoopy ya han respondido. Por supuesto, es el caso peor, ya que la
decisin se toma en el tiempo mximo (ser el hardware del sistema el
que determine ese tiempo), pero, a cambio, es el mtodo ms simple
para implementar (Pentium quad/HP/SUN).
Esperar un tiempo variable (un handshake). Para reducir el tiempo de
espera, se detecta cundo responde el ltimo snoopy, y la decisin se
toma en ese momento. As, en la mayora de los casos la decisin se
toma antes del tiempo mximo, pero es complejo de implementar, ya
que se deben detectar y controlar las respuestas de todos los
dispositivos.
Tanto en el primer caso como en el segundo, una optimizacin tpica
consiste en que, mientras se est esperando, se comienza con la lectura
de memoria; y luego, dependiendo del caso, se aborta el acceso a
memoria (si es que todava no haba terminado) o se bloquea la
respuesta de la memoria hasta que todos los snoopy respondan (SGI
challenge).
Aadir un bit ms a todos los bloques de datos en memoria principal,
para indicar si el bloque est en alguna cache o no. De esta manera, no
hay que esperar a ninguna respuesta, ya que la conoceremos
consultando ese bit. Esta solucin es compleja, porque influye en
todos los bloques de memoria principal, por lo que no se usa.
Para poder aplicar estas estrategias necesitamos ayuda del hardware,
normalmente ms seales en el bus de control. Por un lado, la seal sh, que
ya hemos utilizado, para saber si existen o no copias de un bloque de datos.
Del mismo modo, es conveniente tener otra seal similar, dirty, para
indicar si el bloque est modificado en alguna cache. Por ltimo, es
interesante tener otra tercera seal, inh (inhibir), para poder abortar los
accesos a memoria principal.
3.3
3.3.1.4
109
concesin-bus
recibido
19 En los procesadores actuales esto no es as, ya que el uso de los buses est optimizado.
110
20 O, por ejemplo, el caso de dos escrituras simultneas en fallo en dos procesadores. Los dos piden el
bloque y, si en ese momento nadie dice que lo tiene (sh = 0), los dos lo colocarn en estado M.
3.3
111
- peticin:
- respuesta:
(I S, E)
(I M)
(S M)
112
estado IM, ya que ahora la escritura que queremos hacer partir del
estado I (es un fallo, por lo que hay que conseguir el bloque de
datos: BR, INV).
(M, E M)
PW y acierto
M
BR (BW)
BGR (BR,INV)
INV (BW)
BGR (INV)
IM
INV
SM
PW
PW (BRQ)
PR
BR
PR - BR
sh
nsh
BGR (BR)
INV
PW (BRQ)
ISE
INV
PR (BRQ)
I, -
3.3.2.2
Los problemas comentados hasta ahora no son los nicos que se dan
cuando se implementan protocolos de este tipo. El interbloqueo es otro de
los problemas tpicos. En el campo de las comunicaciones, el interbloqueo
est relacionado con la ocupacin de los buses; en los protocolos de
coherencia, en cambio, puede aparecer otro tipo de interbloqueo: el
denominado fetch deadlock. Veamos un ejemplo.
El controlador de coherencia del procesador P1 est en un estado
transitorio, esperando la respuesta del controlador del bus (y nada ms).
Mientras tanto, el controlador del procesador P2, que ha conseguido el bus,
113
3.4
SNOOPY JERRQUICO
114
C
B1
MP
MP
B2
hardware para la
coherencia global
3.4
SNOOPY JERRQUICO
115
116
MC
IS
MC
MS
ES
rd, fallo
MP
BR @
MC
3
B1
B1
5
KL
KR
KL
MS
KR
ES
MS
ES
B2
MP
3.4.2 Escrituras
Veamos un ejemplo concreto. El procesador P0 del nodo N1 quiere
ejecutar una operacin de escritura ST A en un bloque que est en estado S.
3.4
117
SNOOPY JERRQUICO
N1
wr A
N2
MC
MC
SM
SI
MP
INV A
INV A
B1
N3
MC
SI
SI
MP
B1
MC
INV A
MC
MC
MP
A
B1
3
KL
KL
KR
SI
SM
2 INV A
KR
B2
INV A
KL
KR
SM
3
INV A
Sincronizacin de Procesos
en los Computadores SMP
4.1
INTRODUCCIN
120
P2
...
ST A,F1
...
...
...
...
...
LD F4,A
P2
...
LD
R1,CONT
ADDI R1,R1,#1
ST
CONT,R1
...
...
LD
R1,CONT
ADDI R1,R1,#1
ST
CONT,R1
...
4.1
121
INTRODUCCIN
- ST (P1)
LD (P2) -
122
sabemos, los algoritmos de espera pueden ser de dos tipos: espera activa o
bloqueo. En espera activa, el proceso entra en un bucle en el que
continuamente se pregunta si ya se ha producido una determinada accin;
mientras tanto, el procesador no realiza ninguna tarea til. En los casos de
bloqueo, en cambio, el sistema operativo efecta un cambio de contexto para
pasar a ejecutar otro proceso. El propio sistema operativo se encargar de
despertar al proceso que est en espera cuando se produzca el evento
esperado (o el propio proceso volver cada cierto tiempo a analizar el estado
de la sincronizacin). Ambos mecanismos, espera activa y bloqueo, son
adecuados, y escogeremos uno u otro en funcin de las circunstancias
concretas de la aplicacin y de la mquina (tiempo a esperar, latencia del
cambio de contexto, existencia de otros hilos o threads para ejecutar...);
tambin puede utilizarse un sistema mixto: un tiempo umbral de espera,
seguido de un cambio de contexto. En los ejemplos que vamos a analizar,
utilizaremos un bucle de espera activa.
De quin es la responsabilidad de escribir las rutinas de sincronizacin?
En general, el programador utilizar las rutinas de sincronizacin de la
librera del sistema (ya optimizadas); en todo caso, hay que analizar con
detenimiento el comportamiento de dichas rutinas, porque no todas ellas son
adecuadas para cualquier situacin, situacin que puede variar mucho de
programa a programa o dentro del mismo. Por ejemplo, hay que dar solucin
eficiente al caso de un nico procesador que desea entrar en una seccin
crtica o al caso de P peticiones simultneas de entrada. Una funcin de
sincronizacin que d buen resultado en el primer caso, tal vez no lo d en el
segundo.
Como hemos comentado, la sincronizacin no es algo intrnseco al
algoritmo que se va a ejecutar, sino al hecho mismo de que se quiere ejecutar
en paralelo, en P procesadores, lo que va a generar un trfico de control
especfico. Por ello, un mecanismo de sincronizacin adecuado debe cumplir
algunas condiciones, entre las que cabe destacar:
Baja latencia: se debe gastar el menor tiempo posible en efectuar la
operacin de sincronizacin, sea cual fuera la situacin del programa;
por ejemplo, no se debera perder tiempo en el cerrojo de una seccin
crtica cuando sta est libre y no hay competencia en la entrada.
Trfico limitado: el trfico que se genera en el acceso y uso de las
variables de sincronizacin debe ser el mnimo posible, para evitar
saturar la red de comunicacin.
4.2
123
4.2
La exclusin mutua puede lograrse tambin por medio del hardware. Por
ejemplo, se pueden dedicar algunas lneas del bus de control para utilizarse
124
como variables cerrojo hardware (or-wired, como la seal sh). Sin embargo
no se suele utilizar esa solucin, sino que las funciones lock y unlock se
implementan en software. Veamos cmo podran escribirse esas dos
funciones (CER es una variable tipo cerrojo):
funcin lock(CER)
lock: LD R1,CER
BNZ R1,lock
; saltar si no es 0
funcin unlock(CER)
unlock: ST CER,R0
RET
ADDI R2,R0,#1 ; R2 := 1
ST CER,R2
; cerrar cerrojo
RET
4.2
125
4.2.1.1
Instruccin Test&Set
T&S R1,CER
R1 := MEM[CER]; MEM[CER] := 1;
unlock: ST CER,R0
RET
RET
4.2.1.2
Instruccin Swap
R1 MEM[CER];
126
; R1 := 1
unlock: ST CER,R0
RET
RET
4.2.1.3
Tal como hemos visto, las instrucciones de tipo RMW permiten controlar
el acceso a una seccin crtica, pero tenemos que analizar si se hace de
manera eficiente o no. Como hemos comentado, las funciones de
sincronizacin deben ser de latencia baja y generar poco trfico, todo ello, a
ser posible, independiente del nmero de procesos/procesadores, y con un
reparto equilibrado de los recursos entre los procesos.
Sin embargo, no es eso lo que ocurre. Supongamos que se utiliza un
protocolo tipo MESI (invalidacin) para mantener la coherencia de los datos.
Cada vez que un proceso ejecuta la instruccin T&S se produce una escritura
sobre una variable compartida, el cerrojo. La variable cerrojo estar en
estado S (shared) en la cache y, al ser una escritura, habr que invalidar
todas las copias para mantener la coherencia (snoopy). Esto no es un
problema si somos el nico proceso intentando acceder a la seccin crtica;
sin embargo, si en ese momento hay muchos procesos efectuando la misma
operacin, el prximo intento en todos los procesadores ser un fallo en
cache (se ha anulado la variable cerrojo). Todos los procesos, ms o menos a
la vez, pedirn el bloque de datos correspondiente, por lo que se generar un
trfico de datos muy alto en el bus, ms alto cuanto mayor sea el nmero
de procesos esperando entrar en la seccin crtica. Como consecuencia, las
latencias (el tiempo de respuesta) de dichas operaciones crecern mucho.
En la siguiente figura puede observarse una simulacin de dicha situacin.
Al principio, el procesador P0 est en la seccin crtica y otros cuatro
procesadores esperan para entrar. P0 abandona la seccin crtica y escribe
CER = 0 (unlock), por lo que invalida todas las copias de dicha variable.
Los otros cuatro procesos, a la vez, pedirn (BRQ) el bloque que contiene
CER, para poder ejecutar T&S. Al ser una instruccin atmica, el controlador
del bus sirve las peticiones de manera "ordenada" (FIFO en la figura). Para
indicar la atomicidad, hemos puesto la ejecucin de la instruccin T&S entre
corchetes.
4.2
127
P0 C=0 INV
P1 ? x [TS BRQ
TS INV]
P2 ? x [TS BRQ. . . . . . . . . . . .
SECCIN CRTICA
P3 ? x [TS BRQ. . . . . . . . . . . . . . . . . . . . . . .
P4 ? x [TS BRQ. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
TS INV] [TS. .
repetir y repetir
P + (P 1) k veces
1
4.2.1.4
128
t1 = k c
t 2 = k c2
...
(c > 1)
T&S R1,CER
BNZ R1,esp
RET
4.2.1.5
esp:
CALL ESPERA(t1)
[t1 := ...]
JMP lock
unlock:
ST CER,R0
RET
; t1 = tiempo de espera
; calcular nuevo valor para t1
Procedimiento Test-and-Test&Set
Veamos una segunda alternativa para reducir el trfico. Cada vez que se
ejecuta T&S se escribe un 1 en memoria... aunque el contenido de la
memoria sea precisamente 1. Por qu escribir en la variable cerrojo en
todos los intentos de acceso a la seccin crtica si no se va a modificar su
contenido?
4.2
129
lock:
LD R1,CER
BNZ R1,lock
; fase de test
T&S R1,CER
BNZ R1,lock
; fase de test-and-set
RET
unlock: ST CER,R0
RET
130
P0 C=0 INV
P1 LD x BRQ
LD [TS . . . . . . . . . TS INV]
P2 LD x BRQ. . . . .
LD [TS . . . . . . . . . x BRQ
P3 LD x BRQ. . . . . . . . . . . .
LD [TS . . . . x BRQ. . . . . . . . . . . .
P4 LD x BRQ. . . . . . . . . . . . . .
SECCIN CRTICA
LD . . . . . . . . .
TS INV] LD . . . . x BRQ. .
LD . . . . .
(3P 2) =
p =1
P(3P 1)
2
3P 2
2
4.2.1.6
Resumen de caractersticas
Como hemos visto, las funciones ms simples de tipo T&S para controlar
el acceso a una seccin crtica generan mucho trfico de sincronizacin
cuando existe alta contencin en el acceso a la seccin crtica mientras sta
est ocupada. Pero por otra parte, resultan muy adecuadas en casos de baja
contencin: son muy simples, tienen una latencia muy pequea (pocas
instrucciones) y no generan trfico.
Se utiliza muy poca memoria, ya que basta con una variable,
independientemente del nmero de procesos. Desde el punto de vista del
4.2
131
132
4.2.2.1
Instrucciones LL y SC
R1 := MEM[CER];
LSin[dir] := CER; LSin[flag] := 1;
SC CER,R1
si (LSin[dir,flag] = CER,1) {
MEM[CER] := R1;
LSin[flag] := 0
(INV, todos)
}
R1 := 1/0
(se ha escrito / o no)
4.2
133
ADDI R2,R0,#1
; R2 := 1
l1:
LL R1,CER
BNZ R1,l1
; examinar cerrojo
...
SC CER,R2
BZ R2,lock
RET
unlock: ST CER,R0
RET
134
P0 C=0 INV
P1 LL x BRQ
P2 LL x BRQ. . . . .
P3 LL x BRQ. . . . . . . . . . . .
SECCIN CRTICA
SC] LL. . . . . . . . . . . .
P4 LL x BRQ. . . . . . . . . . . . . .
SC] LL . . . . . . .
SC] LL . . .
( 2P 1) =P
p =1
4.2.2.2
Instruccin Compare&Swap
4.2
135
ADDI R2,R0,#1
; R2 := 1
l1:
C&S R0,R2,CER
BNZ R2,l1
; no escribe siempre
; R2 = 1 no se ha escrito
RET
unlock: ST CER,R0
RET
4.2.2.3
136
Fetch&Incr R1,VAR
R1 := MEM[VAR];
MEM[VAR] := MEM[VAR] + 1;
Fetch&Dcr R1,VAR
R1 := MEM[VAR];
MEM[VAR) := MEM[VAR] 1;
Fetch&Add R1,R2,VAR
R1 := MEM[VAR];
MEM[VAR] := MEM[VAR] + R2;
podemos
Fetch&Incr R1,CONT
4.2
137
4.2.4.1
Tickets
R1,TICKET
; R1 := MEM[TICKET];
; MEM[TICKET]:= MEM[TICKET]+ 1
LL
ADDI
SC
BZ
R1,TICKET
R2,R1,#1
TICKET,R2
R2,tick
; conseguir ticket
; incrementar nmero de ticket para el siguiente
; pero de manera atmica
; repetir la operacin hasta conseguir atomicidad
o bien:
tick:
138
F&I
R1,TICKET
; obtener ticket
esp:
LD
SUB
BNZ
R2,TURNO
R3,R1,R2
R3,esp
; esperar turno
RET
unlock: LD
R1,TURNO
ADDI R1,R1,#1
ST
TURNO,R1
RET
; actualizar turno
; para dar paso al siguiente
4.2
139
4.2.4.2
Vectores de cerrojos
...
...
F&I R1,INDICE
esp:
LD R2,VECT_CER(R1)
BNZ R2,esp
ST MI_INDICE,R1
RET
R1,MI_INDICE
VECT_CER(R1),R2
ADDI R1,R1,#1
ST VECT_CER(R1),R0
RET
; R2 := 1
; recuperar ndice del vector de cerrojos
; cerrar cerrojo propio (1)
; ojo! funcin mdulo
; abrir siguiente cerrojo (0)
140
Tickets
Vectores de cerrojos
P0 TURNO++ INV
P1 LD x BRQ
P2 LD x BRQ. . . . .
VC(i+1)= 0 INV
SEC. CRIT.
LD
LD . . . . . . . . . . . . .
P3 LD x BRQ. . . . . . . . . . . .
P4 LD x BRQ. . . . . . . . . . . . . .
LD
x BRQ
LD
SEC. CRIT.
LD . . . . . . . . .
LD . . . . . . . .
LD . . . . . . . . .
LD . . .
LD . . . . . . . . .
TICK.
1
P
0
P+1
P+3) / 2
V.C.
1
1
1
3
3P
LL/SC:
P2 49 bloques
V.C.:
3P 21 bloques
4.3
4.3
141
P2 (consumidor)
X = F1(Z);
aviso = 1;
(En algunos casos se puede usar el propio resultado como indicador; por ejemplo, si
sabemos que el resultado va a estar en un rango determinado, el consumidor puede
quedarse esperando mientras el resultado est fuera de ese rango.)
142
flag = 1
while (flag == 0) {}
post(flag)
wait(flag)
[ signal(flag) ]
4.4
post(vf,i)
wait(vf,i)
declaracin de la barrera
4.4
143
BARRERA (B,P)
P = nmero de procesos
{
LOCK(B.cer);
if (B.cont == 0) B.estado = 0;
B.cont++;
mi_cont = B.cont;
UNLOCK(B.cer);
if (mi_cont == P)
{
B.cont = 0;
B.estado = 1;
}
else while (B.estado == 0) {};
soy el ltimo
inicializo el contador
abro la barrera
espero hasta que la barrera se abra
144
4.4
145
La variable val_sal es local, una por proceso, e indica el valor actual que permite
salir de la barrera.
BARRERA (B,P)
{
val_sal = !(val_sal);
LOCK(B.cer);
B.cont++;
mi_cont = B.cont;
UNLOCK(B.cer);
if (mi_cont == P)
soy el ltimo
{
inicializo el contador
B.cont = 0;
B.estado = val_sal;
abro la barrera
}
else while (B.estado != val_sal) { }; espero a que se abra la barrera
}
4.4.3 Eficiencia
Los criterios de eficiencia de este tipo de sincronizacin son los mismos
que en el caso anterior: la latencia debe ser baja (no hay que efectuar
muchas operaciones para entrar en la barrera), tiene que generarse poco
trfico, debe escalar bien con el nmero de procesos, etc.
En lo que al trfico que se genera en una barrera de P procesos se refiere,
podemos hacer la siguiente estimacin. Supongamos que las variables de la
barrera (cer, cont y estado) se encuentran en bloques diferentes (para
evitar la falsa comparticin). En general, el proceso Pi tiene que conseguir
cuatro bloques de datos: el de la variable cer, para entrar en la seccin
crtica; el de la variable cont, para incrementar el contador; y el de la
variable estado dos veces, para quedarse en el bucle de espera, y para salir
del mismo, ya que ha sido anulado por el proceso que abre la barrera. Por
tanto, el trfico generado ser del orden de 4P bloques (para ser ms
precisos, 4P 2, ya que el primer y el ltimo proceso necesitan un bloque
menos cada uno).
Analizado en el tiempo, el trfico se va a repartir, en general, de la
siguiente manera: 2 - 3 - 3... - 3 - P1; es decir, el trfico que se genera al
entrar en la barrera suele estar repartido en el tiempo (suponiendo que no hay
146
4.5
RESUMEN
4.5
RESUMEN
147
Consistencia de la Memoria en
los Computadores Paralelos
5.1
INTRODUCCIN
150
5.1
151
INTRODUCCIN
P2
(wr1)
(wr2)
print B;
print A;
(rd1)
(rd2)
152
tiempo
P1
P2
A = 1;
...
...
print B;
B = 2;
...
...
print A;
P2
A = 1;
LISTO = 1;
(wr1)
(wr2)
(rd1)
(rd2)
rd1 (LISTO)
wr2 (LISTO)
rd2 (A)
5.1
153
INTRODUCCIN
P2
F1 = 1;
if (F2 == 0) then
< cdigo >
F2 = 1;
if (F1 == 0) then
< cdigo >
...
...
wr2 (F2)
rd1 (F2)
rd1 (F1)
P2
(wr1)
(wr2)
(rd1)
(rd2)
154
P2
A = 1;
while (A == 0) {};
B = 1;
P3
while (B == 0) {};
C = A;
5.2
155
5.2
156
tiempo
P1
P2
a
b
c
d
En conjunto
SC si
a
b
c
d
SC no
a
c
b
d
a
d
c
b
c
d
b
a
orden
atomicidad
MEM
5.2
157
1. INV
2. ACK
2. ACK
P2
P3
P4
A = 2;
B = 1;
A = 3;
C = 1;
while (B 1) {};
while (C 1) {};
reg1 = A;
while (B 1) {};
while (C 1) {};
reg2 = A;
158
1. BC
2. ACK
3. seguir
5.3
159
P1
P2
P1
P2
A = 1;
B = A;
A = 0;
r1 = 1;
A = r1;
B = r1;
A = 0;
(2 ST)
(2 ST / 1 LD)
5.3
rd >> wr 26
wr >> rd
wr >> wr
160
5.3
161
LD
ST
ST
ST
ST
bferes ST
(FIFO)
MEM
P2
X = nuevo_valor;
Y_copia = Y
Y = nuevo_valor;
X_copia = X
162
imponer el orden estricto (SC) en algunos puntos del programa, para lo que
habr que utilizar las instrucciones especiales que hemos comentado (fence).
Si el procesador no dispone de instrucciones de ese tipo, entonces pueden
utilizarse instrucciones read-modify-write (por ejemplo, T&S) en lugar de los
ST (LD) habituales, ya que esas instrucciones implican una lectura y una
escritura, y por tanto no pueden desordenarse si el modelo de consistencia es
TSO/PC:
ST ... LD
se pueden desordenar
SWAP ... LD
no se pueden desordenar
5.3
163
P2
P1 / P2 / ... / Pn
X = X + 1;
Y = B + 1;
flag = 1;
...
...
while (flag == 0) {};
A = X / 2;
B = Y;
...
lock(cer);
yo = i;
i = i + N;
j = j - 1;
unlock(cer);
...
s >> rd, wr
s >> s
164
5.3.3.1
sinc
rd ...wr ...
sinc
rd ...wr ...
5.3.3.2
5.3
165
s_acq
rd ...wr ...
s_rel
rd ...wr ...
rd ...wr ...
wr>>rd
SC
wr>>wr rd>>rd/wr
sinc.
Instrucc. para
todas
TSO
todas
PC
todas
todas
STBAR, RMW
WO
todas
SYNC
RC
sa >> w/r
w/r >> sr
s >> s
PSO
MEMBAR, RMW
MEMBAR, RMW
REL, ACQ,
RMW
166
SC
wr,rd,s >> wr,rd,s
rd
wr
sinc_a
wr
TSO/PC
wr >> rd
PSO
wr >> wr
= A
= A
WO
RC
rd >> wr, rd
= A
B
= A
B
sinc_acq
sinc_acq
sinc_acq
sinc_acq
sinc_acq
= D
=
= D
=
= D
rd
sinc_r
sinc_rel
sinc_rel
sinc_rel
sinc_rel
sinc_rel
wr
wr
5.4
= D
RESUMEN Y PERSPECTIVAS
Para que los programas paralelos tengan una semntica clara, tanto el
hardware como el programador necesitan que el multiprocesador tenga una
imagen de memoria bien definida. A la imagen o interfaz de memoria del
multiprocesador se le denomina modelo de consistencia.
Existen dos tipos de modelos de consistencia: el secuencial y los
relajados. El primero, SC, impone el orden local y global de todas las
operaciones de memoria, as como la atomicidad de las mismas. Los
modelos relajados, en cambio, permiten el desorden de algunas de esas
operaciones; por ejemplo, pueden adelantarse los LD (TSO), o los LD y los
ST (PSO), o puede admitirse cualquier orden entre ellas pero respetando el
orden con relacin a las operaciones de sincronizacin (WO). Cuando se
utilizan modelos de consistencia relajados, en algunos casos es necesario
imponer el orden estricto, para lo que se utilizan instrucciones especiales
denominadas fence.
5.4
RESUMEN Y PERSPECTIVAS
167
168