Escolar Documentos
Profissional Documentos
Cultura Documentos
2. (2 puntos) Tenemos un procesador superescalar homogeneo de grado 2 (en todas las etapas
se pueden manejar hasta 2 instrucciones por ciclo), con b usqueda alineada y emision alineada y en
orden. Para mantener la consistencia secuencial, as como para renombrar los registros y gestionar
las interrupciones se utiliza un ROB. Existe una estacion de reserva para cada unidad de ejecucion
y el predictor de saltos es estatico y predice que no va a saltar en los saltos hacia adelante, y
que si va a saltar en los saltos hacia atras. Se dispone de las siguientes unidades de ejecucion: dos
unidades de carga/almacenamiento (segmentadas) de latencia 2 (calcula la direccion en el primer
ciclo y accede a la cache en el segundo ciclo), dos ALUs enteras de latencia 1, un sumador en
coma otante (segmentado) de latencia 3, un divisor en coma otante (segmentado) de latencia 4,
y una unidad de saltos que resuelve los saltos en la etapa de ejecucion. Suponemos que en el cauce
de enteros estan implementados los cortocircuitos y reenvos habituales, pero no as en el cauce
de coma otante. Supon para este problema un tama no ilimitado del ROB y de cada una de las
estaciones de reserva.
En dicho ordenador se va a ejecutar la siguiente secuencia de instrucciones que calcula la division
de dos vectores x e y componente a componente:
; el valor inicial de n es bastante grande
lw r3, n ; r3 = n
slli r4, r3, #2 ; r4 = n * 4 (final del vector)
inicio: lf f0, x(r2) ; f0 = x(i)
lf f1, y(r2) ; f1 = y(i)
divf f2, f0, f1 ; f2 = x(i) / y(i)
sf f2, z(r2) ; z(i) = x(i) / y(i)
addui r2, r2, #4 ; r2 = r2 + 4 (incremento el desplazamiento)
sub r5, r4, r2 ; compruebo si he llegado al final
bnez r5, inicio ; saltar a inicio si r5 es distinto de 0
trap #0 ; fin del programa
<sgte.> ; suponemos las instrucciones siguientes enteras
Nota: La instruccion trap no causa la terminacion del programa hasta que se retira del ROB.
Considera que la primera vez que se accede a memoria (para obtener el valor de n y para obtener
el valor de los vectores a partir de r2) se produce un fallo de cache L1 que se resuelve en la cache
L2 con una latencia total de 3 ciclos en el acceso a memoria. El resto de accesos a memoria son
servidos por la cache L1 gracias a la tecnica del prefetching.
a) (1 punto) En que ciclo se conrma la primera instruccion de salto? En que ciclo se conrma la
segunda instruccion de salto? Dibuja el diagrama correspondiente para justicar tu respuesta.
En dicho diagrama indica, para cada instruccion y ciclo de reloj, que fase de la instruccion se
esta ejecutando.
b) (0,5 puntos) Cuantas instrucciones de las dos primeras iteraciones tendra el ROB al acabar
el ciclo en que se conrma la instruccion (addui r2, r2, #4) de la primera iteracion? Para
justicar la respuesta, muestra el contenido del ROB en dicho ciclo.
c) (0,5 puntos) Considera ahora que el procesador tiene un reloj de 1 GHz. y que el regimen
estacionario de ejecucion es igual al de la segunda iteracion. En cuanto tiempo (en segundos)
2
se ejecutara el codigo anterior para un tama no del vector de 1000 elementos? No hace falta que
tengas en cuenta el tiempo necesario para el llenado/vaciado del pipeline. Cuantos MFLOPs
obtendramos para el procesador descrito ejecutando el codigo anterior?
Solucion
a) Para obtener las dos preguntas de este apartado tenemos que simular la ejecucion del programa
durante las dos primeras iteraciones. Obtenemos el siguiente diagrama instruccionestiempo:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
lw r3, n IF IS EX L2 L2 L2 WB C
slli r4, r3, #2 IF IS - - - - EX WB C
lf f0, x(r2) IF IS EX L2 L2 L2 WB C
lf f1, y(r2) IF IS EX - - L2 L2 L2 WB C
divf f2, f0, f1 IF IS - - - - - - EX EX EX EX WB C
sf f2, z(r2) IF IS EX - - - - - - - - - - C(S1)
addui r2, r2, #4 IF IS EX WB - - - - - - - - - C
sub r5, r4, r2 IF IS - EX WB - - - - - - - - C
bnez r5, inicio IF IS - EX - - - - - - - - - C
trap #0 IF XX
lf f0, x(r2) IF IS EX L1 WB - - - - - - - C
lf f1, y(r2) IF IS EX - L1 WB - - - - - - - C
divf f2, f0, f1 IF IS - - - EX EX EX EX WB - - C
sf f2, z(r2) IF IS EX - - - - - - - - - - C(S1)
addui r2, r2, #4 IF IS EX WB - - - - - - - - C
sub r5, r4, r2 IF IS - EX WB - - - - - - - - C
bnez r5, inicio IF IS - EX - - - - - - - - C
trap #0 IF XX
lf f0, x(r2) IF
lf f1, y(r2) IF
En el diagrama denotamos con L1 un acceso a memoria resuelto en la cache L1 y con L2 un
acceso a memoria satisfecho por la cache L2. Como podemos apreciar, los tres primeros accesos
a cache fallan en la L1, siendo resueltos en tres ciclos por la cache L2.
A partir del diagrama anterior vemos que la primera instruccion de salto se conrma en el ciclo
18, mientras que la segunda instruccion de salto lo hace en el ciclo 21.
b) La instruccion addui r2, r2, #4 de la primera iteracion ejecutada se conrma en el ciclo 17.
Al nal de dicho ciclo el contenido del ROB (solo instrucciones de las 2 primeras iteraciones) es
el siguiente:
Entrada ocupado instr. estado dest. valor
1 Si bnez r5, inicio EX
2 Si lf f0, x(r2) WB f0 Mem[x(r2)]
3 Si lf f1, y(r2) WB f1 Mem[y(r2)]
4 Si divf f2, f0, f1 WB f2 #2 / #3
5 Si sf f2, z(r2) EX Mem[z(r2)]
6 Si addui r2, r2, #4 WB r2 r2+4
7 Si sub r5, r4, r2 WB r5 r4 - #6
8 Si bnez r5, inicio EX
El n umero total de entradas del ROB ocupadas es de 8 al nal del ciclo 17. Como se puede ver,
hemos rellenado el campo valor para todas aquellas entradas que ya han pasado por su etapa
WB.
3
c) Del diagrama del apartado a) podemos ver que cada iteracion del bucle en el regimen estacio-
nario tarda en ejecutarse 4 ciclos de reloj (medido como la diferencia entre el comienzo de las
instrucciones de carga en el regimen normal). Por lo tanto, el tiempo que tardan en ejecutarse
1000 iteraciones, sin tener en cuenta los ciclos del llenado/vaciado del pipeline, es el siguiente:
Tiempo = 4 ciclos 1000 = 4000 ciclos = 4 seg
Para el calculo de los MFLOPs, tenemos que en cada iteracion solo realizamos una operacion
en coma otante (la division), por lo que obtendramos:
MFLOPs = 1 op / 4 ciclos @ 1 Ghz = 250 MFLOPs.
6
4. (3 puntos) Dado el siguiente programa secuencial escrito en C:
#include ...
if (max == 0) break;
oat key[256]; key index[pos] = 0;
unsigned char key index[8000]; /* valores entre 0 y 255 */ value = key[max];
oat A[8000][8000]; for (i=0;i<8000;i++) {
for (j=0;j<8000;j++) {
void initialize(void) { A[i][j] = A[i][j] * value;
/* Inicializa los arrays key y }
key index, y la matriz A */ }
} }
void solve(void) {
int max;
int i,j,pos;
oat value; int main() {
initialize();
while (1) { solve();
max = 0; return 0;
for (i=0;i<8000;i++) { }
if (key index[i]>max) {
max = key index[i];
pos = i;
}
}
muestra una version paralela del codigo
1
que utilice 4 hilos y que por tanto pueda ser ejecutado
en un CMP con 4 n ucleos. Supon que nos interesa paralelizar los accesos tanto a la matriz A como a
key index. Para ello, discute las fases en las que habra que organizar el codigo paralelo, las variables
que habra que declarar como compartidas, etc.
Solucion
El programa paralelo lo organizaramos en tres fases: (1) fase de inicializacion, en la que entre
otras cosas se crearan los 3 hilos adicionales para el calculo, (2) fase paralela, que consistira en
la ejecucion del procedimiento solve por parte de los cuatro hilos, y (3) fase de nalizacion en la
empleamos la llamada wait for end(). A su vez, el procedimiento solve se organizara en dos fases:
(1) calculo del maximo elemento en la porcion del array key index que cada hilo tiene asignada y
posteriormente calculo del maximo global de entre los maximos encontrados por cada hilo y (2)
actualizacion de la matriz A.
Los arrays key index y key, y la matriz A habra que declararlos como memoria compartida entre
todos los hilos. Ademas necesitamos un par de variables globales para almacenar el maximo global
(global max) y su posicion en el array key index (global pos). Finalmente necesitamos tambien una
variable global pid que vamos a utilizar para obtener el identicador unico que cada hilo va a tener
asignado. En cuanto a las primitivas de sincronizacion vamos a hacer uso de un cerrojo (l1) y una
barrera (b1).
El codigo pedido quedara como sigue:
1
Utiliza las macros parmacs vistas en clase:
lockdec(lock), lock(lock) y unlock(lock)
bardec(bar) y barrier(bar,num threads)
g malloc(num bytes), create(num threads, proc, arguments) y wait for end(num threads)
7
#include ...
if (max != 0) {
oat *key; LOCK(l1);
unsigned char *key index; if (max > var->global max) {
oat **A; var->global max = max;
struct { var->global pos = pos;
int global pid; }
int global max; UNLOCK(l1);
int global pos; }
} *var; BARRIER(b1);
LOCKDEC(l1); if (var->global max == 0) break;
BARDEC(b1); if (pid == 0) key index[var->global pos] = 0;
value = key[var->global max];
void initialize(void) { for (i=0;i<2000;i++) {
/* Inicializa los arrays key y for (j=0;i<8000;j++) {
key index, y la matriz A */ A[min i+i][j] = A[min i+i][j] * value;
} }
}
void solve(void) { BARRIER(b1);
int max,pid; }
int i,j,pos; }
oat value; int main() {
int min i; key = G MALLOC(array 1-d de 256 elementos oat);
key index = G MALLOC(array 1-d de 8000 elementos char);
LOCK(l1); A = G MALLOC(array 2-d de 8000 por 8000 elementos oat);
pid = var->global pid; var = G MALLOC(struct con 3 elementos enteros);
var->global pid++;
UNLOCK(l1); initialize();
min i = pid*2000; CREATE(3, solve);
while (1) { solve();
max = 0; WAIT FOR END(3);
if (pid==0) var->global max = 0; return 0;
for (i=0;i<2000;i++) { }
if (key index[min i+i]>max) {
max = key index[min i+i];
pos = min i+i;
}
}
8