Академический Документы
Профессиональный Документы
Культура Документы
Procesamiento superescalar
Captación Cola de
(IF) instrucciones
La operación a realizar.
Haciendo uso de esta estructura, la etapa de emisión podrá mandar a ejecutar las
instrucciones en cuanto tengan sus dos campos de operando válido a uno y esté disponible la
unidad funcional que se necesita para la operación. Como se puede observar en la Tabla 1,
las instrucciones se han introducido de forma ordenada (en la etapa de decodificación) en la
estación de reserva o ventana de instrucciones. En el ciclo 3 podrá emitirse la primera
instrucción, dado que tiene sus operandos disponibles y la unidad de ejecución que necesita
también se supone libre. La instrucción (2) necesita el valor de r5 calculado por la instrucción
(1), por lo que tendrá que esperar hasta el ciclo 9 para ser emitida. Por último, las
instrucciones (3) y (4) entran en la ventana de instrucciones en el ciclo 3. Ambas tienen sus
operandos disponibles, pero como sólo hay una única unidad de suma/resta, la instrucción
(4) tendrá que esperar a que se ejecute la instrucción (3) para ser emitida. Como se puede
comprobar, las instrucciones empiezan a ejecutarse (y terminan de hacerlo) en un orden
distinto al que tienen en el código.
Uno de los problemas que se deben afrontar a la hora de diseñar un cauce superescalar es el
de los riesgos de datos. La Figura 2 muestra un ejemplo de los tres tipos de riesgos que
pueden aparecer: RAW (Read-After-Write), WAR (Write-After-Read) y WAW (Write-After-Write).
El primero de ellos aparece cuando una instrucción necesita un operando (read) después
(after) de que sea generado (write) por otra instrucción previa, tal y como ocurre entre las
instrucciones (2) y (1). Para solucionar este tipo de riesgo, la etapa de emisión bloquea a las
instrucciones en la ventana de instrucciones (o bien las etapa de envío en las estaciones de
reserva) hasta que no tengan sus operandos disponibles, tal y como se ha explicado más
arriba.
En cuanto a los riesgos de datos WAR y WAW, realmente no son riesgos de datos
verdaderamente, ya que aparecen debido al uso repetido del mismo registro como registro de
destino de diferentes instrucciones, por lo que se pueden evitar usando diferentes registros
para almacenar los resultados, es decir, renombrando los registros de destino. La Figura 2
muestra un ejemplo de cada uno de estos riesgos. Por ejemplo, entre las instrucciones (4) y
(2) existe un riesgo WAR causado por el uso de r2, ya que aunque la instrucción (4) es
posterior a la instrucción (2), modifica el valor de r2 antes de que se ejecute la instrucción (2),
por lo que cuando se ejecute la instrucción (2) operará con un valor futuro de r2 en lugar de
operar con el valor adecuado. Por otra parte, también existe un riesgo WAW entre las
instrucciones (3) y (1) a causa del uso repetido del registro de destino r5. Como la instrucción
(1) modifica el registro después que la instrucción (3), a partir de ciclo 10 todas las
instrucciones que usen r5 operarán con un valor pasado del registro. Para evitar estos dos
riesgos bastaría con que las instrucciones (3) y (4) escribieran sus resultados en otros
registros, por ejemplo en r7 y r9.
El renombrado de registros es, por tanto, una técnica que hace desaparecer los riesgos WAR
y WAW y puede ser implementada por el compilador, o bien mediante hardware, usando
unas estructuras denominadas búferes de renombrado. En la Figura 3 se muestran dos esquemas
de búferes de renombrado correspondientes a dos alternativas de acceso posibles. En el
búfer de renombrado con acceso asociativo (Figura 3.a) se distinguen cinco campos en cada
línea, de izquierda a derecha:
El campo entrada válida indica, cuando está a 1, que esa línea se está
utilizando para hacer un renombrado de registro.
Cuando llega una instrucción se comprueba asociativamente si alguno de sus operandos está
incluido en el búfer de renombrado. Por ejemplo, en la Figura 3.a se está comprobando si
hay algún renombrado del registro r2 (se supone que es uno de los operandos de una
instrucción) comparando asociativamente con las entradas del búfer de renombrado. Si
hubiera varias entradas que renombraran al registro buscado, se utilizará la línea
correspondiente al último renombrado (la que tenga a 1 campo último).
En el caso de acceso indexado, hay un búfer con una línea para cada uno de los registros del
banco de registros del procesador. En cada una de esas líneas hay un campo entrada válida que
indica (cuando está a 1) si se ha hecho un renombrado al registro correspondiente a esa línea
y otro campo que apunta a una línea del búfer de renombrado propiamente dicha. En esa
línea está el espacio reservado para el renombrado del registro (campo valor) y hay además
otro campo que indica si el valor es válido o no (campo valor válido). Aquí no hay necesidad
de un campo de último dado que en el campo de índice se mantiene el puntero al último
renombrado realizado para el registro de la línea correspondiente.
Así, en un procesador hay consistencia de memoria fuerte si los accesos a memoria para
lectura o escritura se realizan en el mismo orden en que aparecen en el código, y hay
consistencia débil si se permiten accesos a memoria desordenados, siempre y cuando se
respeten las dependencias de datos. En cuanto a la consistencia de procesador, la
consistencia débil permite que las instrucciones se completen desordenadamente
(lógicamente, respetando las dependencias) mientras que en la dependencia fuerte se
completan en el orden en que aparecen en el código. La tendencia en el diseño de los
procesadores ha ido hacia la consistencia de memoria débil y hacia la consistencia de
procesador fuerte.
En la Tabla 2 se muestra un ROB en el que hay cuatro instrucciones que se han introducido
ordenadamente (desde la línea número 3 a la número 6). Los campos de las líneas del ROB
que se muestran en la Tabla 2 tienen el siguiente significado, de izquierda a derecha:
Número de línea del ROB (no hace falta que esté implementado como tal
en la línea).
Campo que indica si el valor almacenado para el dato en la línea del ROB es
válido.
Para que una instrucción pueda retirarse, tanto dicha instrucción como todas las que estén en
líneas anteriores del ROB tienen que tener el campo valor válido (o el campo flush) con el valor
1. Como se puede ver en la Tabla 2, la suma (en la línea 5 del ROB) ha terminado de
ejecutarse pero todavía no ha escrito su resultado en el registro r1 dado que no puede
retirarse antes que las instrucciones de las líneas anteriores del ROB. En esta implementación
del ROB que hemos descrito, el renombrado de registros se hace en el ROB, por lo que no
sería necesario añadir a nuestro procesador búferes de renombrado. El ROB es una
estructura muy útil. De hecho, con ayuda del campo flush puede ayudar también en el
procesamiento de interrupciones y saltos, como veremos a continuación.
NT NT NT
T 11 10 01 00 NT
T T T
Tomado Tomado No tomado No tomado
fuerte débil débil fuerte
Figura 4. Diagrama de estados para predicción dinámica con dos bits de historia.
El ROB facilita el procedimiento de recuperación tras una predicción incorrecta. Para ello se
puede añadir un campo nuevo a cada línea, pred, que permite marcar las instrucciones que se
hayan introducido en el cauce tras la predicción de un salto (incluso se puede indicar el tipo
de predicción, T o NT que se haya hecho). Además, se añade un bit (frecuentemente
denominado bit de vaciado o de flush) a cada línea. Este bit de vaciado se activa, en todas las
instrucciones que se introdujeron tras la instrucción de salto, en el momento en que se
resuelve la condición de salto y, al procesar la instrucción de salto, se determina que la
predicción era incorrecta. Todas las instrucciones que tienen ese bit activado (todas las que se
habían introducido especulativamente en el cauce) se retiran del ROB sin realizar ninguna
modificación en el procesador.
y suponiendo que se pueden captar cuatro instrucciones por ciclo y emitir cuatro
instrucciones por ciclo, indique el orden en que se emitirán las instrucciones para cada uno
de los siguientes casos:
c) Una estación de reserva de tres líneas para cada unidad funcional, con envío
ordenado y ventana deslizante.
NOTA: Considere que hay una unidad funcional para la carga (2 ciclos), otra para el almacenamiento
(1 ciclo), tres para la suma/resta (1 ciclo), y una para la multiplicación (6 ciclos).
Solución
La Figura 5 muestra la evolución de las instrucciones en un cauce con una ventana de instrucciones
centralizada con emisión ordenada y alineada. En este caso, hasta que no se han emitido todas las
instrucciones que entraron en la ventana al decodificarse, no se introducen nuevas instrucciones que
puedan ser emitidas. Esta situación se muestra en la figura mediante una línea gruesa. A continuación
se comentan los atascos que se producen en el cauce:
Ciclo 5:
La instrucción (3) debe retrasarse hasta que la instrucción (1) haya cargado el
valor de r1.
Ciclo 7:
La instrucción (4) debe retrasarse hasta que la instrucción (2) haya cargado el
valor de r2.
Las instrucciones (6) y (7) deben esperar a que se emita la (5) porque la emisión
es ordenada.
Ciclo 14:
Ciclo 16:
INSTRUCCIÓN 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
lw r1, 0x1ac IF ID EX
lw r2, 0xc1f IF ID EX
add r3, r0, r0 IF ID EX
mul r4, r2, r1 IF ID EX
add r3, r3, r4 IF ID EX
add r5, r0, 0x1ac IF ID EX
add r6, r0, 0xc1f IF ID EX
sub r5, r5, #4 IF ID EX
sub r6, r6, #4 IF ID EX
sw (r5), r3 IF ID EX
sw (r6), r4 IF ID EX
Figura 5. Traza de la ejecución del código del problema 1 usando una ventana de instrucciones
centralizada con emisión ordenada y alineada.
INSTRUCCIÓN 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
lw r1, 0x1ac IF ID EX
lw r2, 0xc1f IF ID EX
add r3, r0, r0 IF ID EX
mul r4, r2, r1 IF ID EX
add r3, r3, r4 IF ID EX
add r5, r0, 0x1ac IF ID EX
add r6, r0, 0xc1f IF ID EX
sub r5, r5, #4 IF ID EX
sub r6, r6, #4 IF ID EX
sw (r5), r3 IF ID EX
sw (r6), r4 IF ID EX
Figura 6. Traza de la ejecución del código del problema 1 usando una ventana de instrucciones
centralizada con emisión desordenada y alineada.
La Figura 6 muestra la evolución de las instrucciones en un cauce con una ventana de instrucciones
centralizada con emisión desordenada y alineada. Los cambios con respecto a la situación anterior son:
Ciclo 3:
Ciclo 8:
Ciclo 13:
Las instrucciones (9) – (11) se han podido decodificar un ciclo antes, ya que la
emisión desordenada ha permitido que se vacíe la ventana de instrucciones un
ciclo antes.
En el caso se utilizar estaciones de reserva, las instrucciones se emiten desde el decodificador a cada
estación de reserva en la etapa de decodificación. Desde ahí se envían a las correspondientes unidades
funcionales. Se ha supuesto que la emisión a las estaciones de reserva se hace de forma que se
distribuyen las instrucciones entre todas las unidades del mismo tipo, para minimizar las colisiones y
los tiempos de espera en la correspondiente estación. Como muestra la Figura 7, en este caso el
tiempo de ejecución del programa está determinado por el riesgo estructural en la unidad de carga
entre las instrucciones (1) y (2), y por las dependencias RAW entre las instrucciones (4) y (2), (5) y (4),
(10) y (5), y (11) y (10).
INSTRUCCIÓN 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
lw r1, 0x1ac IF ID EX
lw r2, 0xc1f IF ID EX
add r3, r0, r0 IF ID EX
mul r4, r2, r1 IF ID EX
add r3, r3, r4 IF ID EX
add r5, r0, 0x1ac IF ID EX
add r6, r0, 0xc1f IF ID EX
sub r5, r5, #4 IF ID EX
sub r6, r6, #4 IF ID EX
sw (r5), r3 IF ID EX
sw (r6), r4 IF ID EX
Figura 7. Traza de la ejecución del código del problema 1 usando una estación de reserva de tres líneas
para cada unidad funcional, con envío ordenado y ventana deslizante.
Solución
La Figura 8 muestra el resultado de insertar la primera instrucción de la secuencia en el búfer de
renombrado. Se ha supuesto que los registros r0 y r1 estaban previamente renombrados y con valores
válidos en las entradas 2 y 4 del búfer, y se ha reservado la entrada 6 para almacenar el resultado de la
instrucción, por tanto, dicha entrada permanecerá marcada como no válida hasta que el resultado esté
disponible.
La Figura 9 muestra el estado del búfer tras la inserción de la instrucción de suma. Se reserva la
entrada 5 del búfer para almacenar el resultado de la instrucción, se marca como no válida, y como el
valor de r2 todavía no está disponible, se indica que el valor de dicho registro se tomará de la entrada 6
del búfer cuando esté disponible.
Por último, la Figura 10 muestra el contenido del búfer de renombrado tras la inserción de la última
instrucción de la secuencia. Se reserva la entrada 7 para el nuevo valor de r2 y se marca como no
válida. Las dos instrucciones anteriores no se ven afectadas por este nuevo renombrado, ya que la
multiplicación almacenará el valor anterior de r2 en la entrada 6, de la que lo tomará la suma,
independientemente del resultado de la resta, que se almacenará en la entrada 7.
REGISTRO ENTRADA ÍNDICE VALOR VÁLIDO
VÁLIDA BÚFER
0 1 2
1 1 4
2 1 6 10 1
3
15 1
3. Suponga que las siguientes instrucciones se introducen una tras otra (en los ciclos indicados
entre paréntesis) en un búfer de renombrado con acceso asociativo.
NOTA: La multiplicación tarda 6 ciclos, y la suma y la resta 2 ciclos, y hay suficientes unidades
funcionales como para que no afecten los riesgos estructurales.
Solución
La Tabla 4 muestra la evolución del búfer de renombrado a lo largo de la ejecución de las
instrucciones del fragmento de código del enunciado, marcando en negrita los cambios que ocurren
en cada ciclo. Se ha supuesto que los registros f1 y f2 están previamente renombrados y con los valores
válidos 2.0 y 3.0 respectivamente. A continuación se describe brevemente el contenido de la tabla:
La Figura 11 muestra la traza de ejecución de la secuencia de instrucciones. Sólo se han dibujado las
etapas de decodificación y ejecución, ya que es en la primera en la que se introducen las instrucciones
en el búfer de renombrado y en la segunda en la que se ejecutan las instrucciones. Como la
multiplicación tiene sus dos operandos disponibles, se comenzará su ejecución en el siguiente ciclo, y
se terminará en el ciclo 9. La operación de suma de addd f2, f3, f1 no podrá ejecutarse antes del ciclo 10
(cuando termine la multiplicación), y tomará el valor de f3 de la entrada 2 del búfer de renombrado.
Terminará en el ciclo 11, y el resultado se escribirá en la entrada 3 del búfer. La instrucción subd
f3, f3, f1 tomará el valor de f1 de la entrada 1 del búfer (su valor es 2.0) y tomará el valor de f3 que
necesita de la entrada 2 del búfer. Esta operación empezará a ejecutarse en el ciclo 10 y terminará en el
ciclo 11 escribiendo el resultado en la entrada 4. En cuanto a la instrucción addd f5, f1, f2, tomará el
valor de f1 de la entrada 1 del búfer (su valor es 2.0) y tomará el valor de f2 que necesita de la entrada 3
del búfer. Esta operación empezará a ejecutarse en el ciclo 12 y terminará en el ciclo 13.
INSTRUCCIÓN 3 4 5 6 7 8 9 10 11 12 13
multd f3, f1, f2 ID EX
addd f2, f3, f1 ID EX
subd f3, f3, f1 ID
addd f5, f1, f2 ID EX
La Tabla 5 muestra los momentos de inicio y finalización de las instrucciones de la secuencia así como
sus valores finales. De esta tabla se pueden obtener los valores finales para los registros de la
arquitectura, que serán f1 = 2.0, f2 = 8.0, f3 = 4.0, f5 = 10.0.
4. Suponga que las siguientes instrucciones se introducen una tras otra (en los ciclos indicados
entre paréntesis) en un búfer de renombrado con acceso asociativo.
NOTA: La unidad de multiplicación tarda 5 ciclos, y la de suma/resta 2 ciclos, y cada unidad dispone
de una estación de reserva con espacio suficiente para tres instrucciones.
Solución
La Tabla 6 muestra la evolución del búfer desde el ciclo 3 al ciclo 6, marcando en negrita los cambios
que ocurren en cada ciclo. A continuación se describe brevemente su contenido:
INSTRUCCIÓN 3 4 5 6 7 8 9 10 11 12 13 14
multd f3, f1, f2 ID EX
addd f2, f3, f1 ID EX
subd f3, f3, f1 ID EX
multd f5, f1, f4 ID EX
addd f6, f2, f3 ID EX
Conforme vaya finalizando la ejecución de las instrucciones, se irán escribiendo sus resultados en el
campo valor de sus entradas del búfer de renombrado. En el momento de escribir el valor, se
cambiará el campo valor válido de 0 a 1 y cualquier instrucción que esté esperando el dato escrito
podrá pasar a ejecutarse. Teniendo en cuenta las dependencias de datos, las latencias de las unidades
de ejecución, y que solamente hay un sumador y un multiplicador, los ciclos de inicio y finalización de
la ejecución de las instrucciones son los que se muestran en la Figura 12. Sólo se han dibujado las
etapas de decodificación y ejecución, ya que es en la primera en la que se introducen las instrucciones
en el búfer de renombrado y en la segunda en la que se ejecutan las instrucciones.
Aumentando el número de sumadores y de multiplicadores a 2, eliminamos todos los riesgos
estructurales y conseguimos que los únicos atascos en el cauce se deban a dependencias entre datos, lo
que nos ahorra dos ciclos en la ejecución del programa, como muestra la Figura 13.
INSTRUCCIÓN 3 4 5 6 7 8 9 10 11 12
multd f3, f1, f2 ID EX
addd f2, f3, f1 ID EX
subd f3, f3, f1 ID EX
multd f5, f1, f4 ID EX
addd f6, f2, f3 ID EX
Figura 13. Traza de la ejecución del código del problema 4 aumentando el número de unidades de
ejecución.
5. Suponga que las siguientes instrucciones se han decodificado en los ciclos indicados entre
paréntesis, introduciéndose en una estación de reserva común para todas las unidades
funcionales de coma flotante.
NOTA: La multiplicación tarda 4 ciclos, y la suma y la resta 2 ciclos. Hay tantas unidades funcionales
como sea necesario para que no haya riesgos estructurales. Se pueden enviar, retirar, etc., dos
instrucciones por ciclo como máximo.
Solución
Para resolver el problema se parte de la Figura 14, en la que se indican los ciclos en los que las
instrucciones se terminan de decodificar (ID) y han pasado a la estación de reserva, los ciclos en los
que comienza y termina la ejecución de la operación correspondiente a la instrucción (EX), los ciclos
en los que el resultado de la operación se ha almacenado en el ROB, y el momento en que después de
retirar la instrucción del ROB, los resultados se han almacenado en el banco de registros de la
arquitectura (WB). Esta figura constituye la respuesta al segundo del problema. Las instrucciones
segunda y tercera deben esperar que termine la ejecución de la primera, y la cuarta instrucción espera
que termine la segunda.
INSTRUCCIÓN 1 2 3 4 5 6 7 8 9 10 11 12
multd f3, f1, f2 IF ID EX ROB WB
addd f2, f3, f1 IF ID EX ROB WB
subd f3, f3, f1 IF ID EX ROB WB
addd f4, f1, f2 IF ID EX ROB WB
El ROB empieza a llenarse al final del ciclo 2, después de haberse decodificado las
dos primeras instrucciones.
Hasta el ciclo 7 no ocurre nada en el ROB (en relación con las instrucciones que
indica el problema). Al final de este ciclo se habrá terminado la multiplicación, y el
resultado estará almacenado en el campo de valor de la entrada 0 del búfer, el bit de
valor válido estará a 1, y también se habrá iniciado la ejecución de las instrucciones
(2), y (3).
Al final del ciclo 9 habrá terminado la ejecución de las instrucciones (2) y (3) y sus
resultados estarán almacenados en las entradas 1 y 2 el ROB, y habrá empezado la
ejecución de la instrucción (4).
Al final del ciclo 10 se habrán retirado las instrucciones (2) y (3) y se escribirán sus
resultados en los registros f2 y f3.
f1 = 3.0
f2 = 9.0
f3 = 3.0
f4 = 12.0
El procesador es capaz de captar, decodificar, emitir y retirar hasta dos instrucciones por
ciclo, y las estaciones de reserva pueden realizar envíos no alineados y desordenados a las
unidades de ejecución. Si los registros f1 y f2 tienen inicialmente los valores 10.0 y 5.0, ¿qué
valores se obtendrán tras la ejecución del siguiente programa y en qué ciclos se escribirá en
los registros de la arquitectura?
Solución
La Figura 15 muestra una traza de la ejecución del programa en el procesador que se detalla en el
enunciado. A continuación se describe lo que ocurre en el procesador para cada instrucción:
La instrucción (2) también se emite en el ciclo 2 a RS1, pero como tiene una
dependencia RAW con la instrucción (1) en f3, debe esperar a que f3 se haya
calculado para poder ejecutarse. En cuanto tiene disponible f3 (ciclo 5) pasa a
ejecutarse al sumador 1 y almacena el resultado en el ROB en el ciclo 7 (los
sumadores tienen una latencia de 2 ciclos). En el siguiente ciclo (ciclo 8) se retirará
del ROB y almacenará en el registro f2 el valor 20.
La instrucción (3) se emite en el ciclo 3 a la estación de reserva RS2, ya que las dos
primeras se emitieron en el ciclo 2 y sólo se pueden emitir dos instrucciones por
ciclo. Esta instrucción no podrá ejecutarse hasta el ciclo 7, ya que tiene
dependencias RAW con las instrucciones (1) y (2) en los registros f3 y f2
respectivamente, y almacenará su resultado en el ROB en el ciclo 12 porque el
multiplicador tiene una latencia de 5 ciclos. En el ciclo 13 se retirará del ROB
escribiendo en el registro f4 el valor 300.
INSTRUCCIÓN 1 2 3 4 5 6 7 8 9 10 11 12 13 14 … 46 47 48
addd f3, f1, f2 IF ID EX ROB WB
addd f2, f3, f2 IF ID EX ROB WB
multd f4, f3, f2 IF ID EX ROB WB
divd f5, f2, f1 IF ID EX … ROB WB
subd f2, f3, f1 IF ID EX ROB … WB
NOTA: Considere que el procesador tiene una unidad funcional de carga con una latencia de 2 ciclos,
una unidad de almacenamiento con una latencia de 1 ciclo, tres unidades de suma/resta con
una latencia de 1 ciclo, una unidad de multiplicación con una latencia de 6 ciclos, y que no
hay limitaciones para el número de líneas de la cola de instrucciones, ventana de
instrucciones, búfer de reordenamiento, puertos de lectura/escritura etc.
Solución
En la emisión ordenada (Figura 16) los instantes en los que las instrucciones empiezan a ejecutarse
(etapa EX) deben estar ordenados de menor a mayor, a diferencia de lo que ocurre en la emisión
desordenada (Figura 17). Dado que el procesador utiliza un búfer de reordenamiento (ROB), la
finalización del procesamiento de las instrucciones es ordenada y por ello, las etapas WB de las
instrucciones (momento en que se retiran las instrucciones del ROB y se escriben en los registros de la
arquitectura) deben estar ordenadas en ambas tablas.
INSTRUCCIÓN 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
lw r3, 0x10a IF ID EX ROB WB
addi r2, r0, #128 IF ID EX ROB WB
add r1, r0, 0x0a IF ID EX ROB WB
lw r4, 0(r1) IF ID EX ROB WB
lw r5, –8(r1) IF ID EX ROB WB
mult r6, r5, r3 IF ID EX ROB WB
add r5, r6, r3 IF ID EX ROB WB
add r6, r4, r3 IF ID EX ROB WB
sw 0(r1), r6 IF ID EX ROB WB
sw –8(r1), r5 IF ID EX ROB WB
sub r2, r2, #16 IF ID EX ROB WB
Figura 16. Traza de la ejecución del código del problema 7 usando una emisión ordenada.
INSTRUCCIÓN 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
lw r3, 0x10a IF ID EX ROB WB
addi r2, r0, #128 IF ID EX ROB WB
add r1, r0, 0x0a IF ID EX ROB WB
lw r4, 0(r1) IF ID EX ROB WB
lw r5, –8(r1) IF ID EX ROB WB
mult r6, r5, r3 IF ID EX ROB WB
add r5, r6, r3 IF ID EX ROB WB
add r6, r4, r3 IF ID EX ROB WB
sw 0(r1), r6 IF ID EX ROB WB
sw –8(r1), r5 IF ID EX ROB WB
sub r2, r2, #16 IF ID EX ROB WB
Figura 17. Traza de la ejecución del código del problema 7 usando una emisión desordenada.
Otro aspecto que debe tenerse en cuenta a la hora de realizar la traza es la posibilidad de que ocurran
riesgos estructurales. En este caso, debido a que sólo hay una unidad de carga, aparece un riesgo
estructural entre las instrucciones (4) y (5), lo que provoca que la ejecución de la instrucción (5) se
tenga que retrasar hasta el ciclo 7. Además hay que tener en cuenta que se decodifican, emiten,
escriben en el ROB, o retiran, dos instrucciones por ciclo como máximo, por tanto, en un mismo ciclo
no puede haber más de dos instrucciones en las etapas ID, EX, ROB, y WB. Esta limitación afecta a la
instrucción (11) en la Figura 17 que escribe el resultado en el ROB en el ciclo 10, y no en el 9.
Como excepción a la regla anterior tenemos el caso de las instrucciones de almacenamiento en la etapa
WB. Se ha supuesto que la limitación de retirar hasta dos instrucciones por ciclo se deriva de que sólo
hay dos puertos de escritura en el banco de registros, pero como las instrucciones de almacenamiento
no escriben en el banco de registros, en un mismo ciclo se podrán retirar hasta dos instrucciones que
escriban en el banco de registros y además todas las instrucciones de almacenamiento que hayan
finalizado.
Para resolver la segunda cuestión, inicialmente se considera que se decodifican el mismo número de
instrucciones que se captan, ya que no existen limitaciones impuestas por las instrucciones al ritmo de
decodificación (éste viene determinado por las posibilidades de los circuitos de descodificación y la
capacidad para almacenar las instrucciones decodificadas hasta que se emitan). También se considera
que no existen limitaciones para el número de instrucciones por ciclo que se emiten, escriben el ROB,
y se retiran. Por último, se consideran que están disponibles todas las unidades funcionales que se
necesiten para que no haya colisiones (riesgos estructurales).
INSTRUCCIÓN 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
lw r3, 0x10a IF ID EX ROB WB
addi r2, r0, #128 IF ID EX ROB WB
add r1, r0, 0x0a IF ID EX ROB WB
lw r4, 0(r1) IF ID EX ROB WB
lw r5, –8(r1) IF ID EX ROB WB
mult r6, r5, r3 IF ID EX ROB WB
add r5, r6, r3 IF ID EX ROB WB
add r6, r4, r3 IF ID EX ROB WB
sw 0(r1), r6 IF ID EX ROB WB
sw –8(r1), r5 IF ID EX ROB WB
sub r2, r2, #16 IF ID EX ROB WB
Figura 18. Traza de la ejecución del código del problema 7 usando una emisión desordenada y sin
restricciones en el número de unidades de ejecución, instrucciones procesadas por etapa, tamaño de los
búferes, etc.
Una vez encontrada la distribución temporal de las instrucciones en las distintas etapas, tal y como se
muestra en la Figura 18, se observa que, las mejoras necesarias (sin modificar los tiempos de
procesamiento de las unidades funcionales) para reducir el tiempo al mínimo que permiten las
dependencias RAW entre las instrucciones han sido: decodificar 4 instrucciones por ciclo, emitir,
escribir en el ROB, y retirar hasta tres instrucciones por ciclo, y añadir una unidad de carga de
memoria más.
INSTRUCCIÓN 1 2 3 4 5 6 7 8 9 10 11 12
lw r3, 0x10a IF ID EX ROB WB
addi r2, r0, #128 IF ID EX ROB WB
add r1, r0, 0x0a IF ID EX ROB WB
lw r4, 0(r1) IF ID EX ROB WB
lw r5, –8(r1) IF ID EX ROB WB
mult r6, r5, r3 IF ID EX ROB WB
add r5, r6, r3 IF ID EX ROB WB
add r6, r4, r3 IF ID EX ROB WB
sw 0(r1), r6 IF ID EX ROB WB
sw –8(r1), r5 IF ID EX ROB WB
sub r2, r2, #16 IF ID EX ROB WB
Figura 19. Traza de la ejecución del código del problema 7 usando una emisión desordenada,
procesando hasta res instrucciones por ciclo, con dos unidades de carga y con un multiplicador de tres
ciclos de latencia.
Si se tiene en cuenta que la secuencia consta de 11 instrucciones, que el tiempo mínimo que tarda la
primera instrucción en salir son 6 ciclos (lo tomamos como tiempo de latencia de inicio del cauce), y
que el tiempo total de ejecución en este caso es de 12 ciclos, se puede escribir:
con lo que, si se despeja, se tiene que el procesador superescalar presenta una media de 0.6 ciclos por
instrucción, o lo que es lo mismo, ejecuta 1.67 instrucciones por ciclo.
Solución
La Tabla 8 muestra la evolución del búfer de reordenamiento marcando en negrita los cambios que se
producen en cada ciclo:
En el ciclo 11 se retiran las instrucciones (7), (8) y (9) y se indica que la instrucción
(10) ya ha escrito en memoria.
NOTA: El procesador dispone de 2 unidades de suma/resta (de 2 ciclos), una de multiplicación (de 4
ciclos), y que no hay limitaciones en el número de líneas de la cola de instrucciones, búfer de
reordenamiento, puertos de lectura/escritura, etc.
Solución
En la Figura 20 se muestra la evolución temporal del conjunto de instrucciones indicado usando una
emisión ordenada (no alineada).
INSTRUCCIÓN 1 2 3 4 5 6 7 8 9 10 11 12
subd f2, f2, f1 IF ID EX ROB WB
addd f4, f2, f3 IF ID EX ROB WB
subd f5, f2, f3 IF ID EX ROB WB
multd f6, f2, f3 IF ID EX ROB WB
subd f2, f2, f5 IF ID EX ROB WB
subd f7, f4, f6 IF ID EX ROB WB
Figura 20. Traza de la ejecución del código del problema 9 usando emisión ordenada.
Las instrucciones (2), (3), y (4) han de esperar a que termine de ejecutarse la instrucción (1) para
disponer de su operando f2. La instrucción (5) también tiene que esperar al operando f2, pero como
también necesita f5, que es producida por la instrucción (3), debe esperar hasta que haya terminado
ésta. Por otra parte, tampoco podría enviarse, dado que no se pueden enviar más de tres instrucciones
por ciclo, y se envían las instrucciones (2), (3), y (4) en el ciclo 5. Por último, la instrucción (6) debe
esperar que termine la (4) porque depende de f6.
Si la emisión es desordenada no se ganaría nada para las instrucciones indicadas, ya que lo que limita
su emisión son las dependencias RAW entre ellas. Ninguna instrucción posterior a la instrucción (1) se
puede enviar antes del ciclo 5 (la instrucción (1) produce f2 que es consumido por las instrucciones
(2), (3), (4), y (5)). La instrucción (5) no puede enviarse antes del ciclo 7, ya que necesita el valor de f5
que produce la instrucción (3). La instrucción (6) no puede lanzarse antes del ciclo 9 dado que necesita
el valor de f6, que se tiene en el ciclo 8, obtenido por la instrucción (4).
Como hemos dicho antes, todas las instrucciones que se retrasan en la secuencia de código lo hacen
por un riesgo RAW, así que no conseguiríamos ninguna mejora añadiendo más unidades de ejecución.
Sin embargo, si las unidades de ejecución fueran un ciclo más rápidas, el programa tardaría 9 ciclos
independientemente de si la emisión es o no ordenada, como muestra la Figura 21. Por lo tanto, para
este programa es mejor reducir el tiempo de ejecución de las unidades funcionales existentes que
añadir nuevas unidades de ejecución.
INSTRUCCIÓN 1 2 3 4 5 6 7 8 9
subd f2, f2, f1 IF ID EX ROB WB
addd f4, f2, f3 IF ID EX ROB WB
subd f5, f2, f3 IF ID EX ROB WB
multd f6, f2, f3 IF ID EX ROB WB
subd f2, f2, f5 IF ID EX ROB WB
subd f7, f4, f6 IF ID EX ROB WB
Figura 21. Traza de la ejecución del código del problema 9 usando unidades de ejecución un ciclo más
rápidas.
10. Suponga un procesador superescalar en el que se pueden captar y decodificar hasta dos
instrucciones por ciclo, emitir hasta tres instrucciones por ciclo como máximo, y retirar hasta
dos instrucciones por ciclo. La emisión es desordenada y no alineada y se realiza
directamente a las unidades de ejecución, es decir, que el procesador no dispone de
estaciones de reserva. La ejecución también es desordenada, y para permitir la finalización
ordenada, se dispone de un búfer de reordenamiento (ROB) en el que se introducen las
instrucciones una vez decodificadas y del que se retiran en orden una vez que han finalizado.
a) Indique las dependencias entre las instrucciones, los ciclos en los que se
emiten para su ejecución y cómo evolucionaría en búfer de reordenamiento
hasta que se hayan retirado todas las instrucciones de la siguiente secuencia:
NOTA: La suma y la resta consumen 1 ciclo de reloj y la multiplicación tres ciclos. Considere que no
hay limitaciones en la capacidad de los búferes ni en el número de unidades funcionales. Se
supone que f1, f2 y f5 tienen valores previos.
Solución
Ya que el procesador no dispone de estaciones de reserva, la lógica de emisión tiene que esperar a que
los operandos le sean facilitados por la lógica de bypass, por tanto, los riesgos RAW entre las
instrucciones (3), (4) y (6) y la instrucción (1), a causa de f1, afectarán al orden de emisión de las
instrucciones.
INSTRUCCIÓN 1 2 3 4 5 6 7 8 9
multd f1, f1, f5 IF ID EX ROB WB
addd f2, f2, f5 IF ID EX ROB WB
addd f4, f1, f2 IF ID EX ROB WB
addd f6, f1, f5 IF ID EX ROB WB
multd f5, f2, f2 IF ID EX ROB WB
subd f6, f2, f1 IF ID EX ROB WB
Teniendo en cuenta estas dependencias, las instrucciones se ejecutarían como se muestra en la Figura
22. En cuanto al búfer de reordenamiento, su evolución se detalla en la Tabla 9:
número de ciclos 9
T 4.5 ns
F 2 109
Para la calcular la velocidad pico, como se pueden retirar hasta dos instrucciones por ciclo, y la
frecuencia del procesador es de 2 GHz, suponiendo que no hubiera atascos en el cauce se podría
alcanzar:
11. Suponga un procesador superescalar en que se captan cuatro instrucciones por ciclo, se
decodifican tres instrucciones por ciclo, se emiten tres instrucciones por ciclo como máximo,
y se retiran hasta tres instrucciones por ciclo. La emisión y la ejecución son desordenadas, y
las instrucciones, una vez decodificadas, se introducen en un búfer de reordenamiento
(ROB) que permite la finalización ordenada del procesamiento de las instrucciones.
a) Indique las dependencias entre instrucciones y cómo evolucionaría el búfer
de reordenamiento hasta que se hayan retirado todas las instrucciones de la
secuencia:
NOTA: La suma y la resta consumen un ciclo de reloj y la multiplicación cuatro ciclos. Considere que
no hay limitaciones en la capacidad de los búferes, y en el número de unidades funcionales.
Se supone que f1, f2, y f4 tienen valores válidos previos.
Solución
Analizando el código del enunciado se detecta fácilmente que las instrucciones (2) y (3) dependen del
valor de f1 producido por la instrucción (1) y que la instrucción (4) depende del valor de f6 producido
por la instrucción (3). Teniendo en cuenta estas dependencias, las instrucciones se ejecutarían como se
muestra en la Figura 23.
INSTRUCCIÓN 1 2 3 4 5 6 7 8 9
addd f1, f1 ,f4 IF ID EX ROB WB
multd f3, f1, f2 IF ID EX ROB WB
addd f6, f1, f4 IF ID EX ROB WB
subd f4, f1, f6 IF ID EX ROB WB
Teniendo en cuenta la traza de ejecución del código, la Tabla 10 muestra el estado del ROB en cada
durante la ejecución del fragmento de código, resaltando en negrita los cambios producidos en cada
ciclo de la ejecución. A continuación se describe la evolución del búfer de reordenamiento a lo largo
de la ejecución:
número de ciclos 9
T 4.5 ns
F 2 109
Para la calcular la velocidad pico, como sólo se pueden retirar tres instrucciones por ciclo, suponiendo
que no hubiera atascos en el cauce:
a) Indique las dependencias entre las instrucciones, los ciclos en los que se
emiten para su ejecución y cómo evolucionaría en búfer de reordenamiento
hasta que se hayan retirado todas las instrucciones de la siguiente secuencia
almacenada en la cola de instrucciones captadas:
multd f1, f1, f5 ; (1)
addd f2, f2, f5 ; (2)
divd f4, f1, f2 ; (3)
addd f6, f1, f5 ; (4)
multd f5, f2, f2 ; (5)
subd f6, f2, f1 ; (6)
NOTA: La suma y la resta consumen 1 ciclo de reloj, la multiplicación tres ciclos y la división cuatro
ciclos. Considere que sólo hay un multiplicador, un divisor, y dos unidades para
sumar/restar, y que no hay limitaciones en la capacidad de los búferes. Se supone que f1, f2 y
f5 tienen valores previos.
Solución
La Figura 24 muestra una traza de la ejecución del programa de la que puede obtener su tiempo de
ejecución, los ciclos en los que se emite cada instrucción. También ilustra los riesgos RAW
ocasionados entre las instrucciones (3), (4) y (6) y la instrucción (1) ocasionados por el uso del registro
f1.
INSTRUCCIÓN 1 2 3 4 5 6 7 8 9 10 11 12
multd f1, f1, f5 IF ID EX ROB WB
addd f2, f2, f5 IF ID EX ROB WB
divd f4, f1, f2 IF ID EX ROB WB
addd f6, f1, f5 IF ID EX ROB WB
multd f5, f2, f2 IF ID EX ROB WB
subd f6, f2, f1 IF ID EX ROB WB
La evolución de búfer de reordenamiento se muestra en la Tabla 11, marcando en negrita los cambios
que se producen en cada ciclo de la ejecución:
número de ciclos 12
T 6 ns
F 2 109
Para la calcular la velocidad pico, como se pueden retirar hasta dos instrucciones por ciclo, y la
frecuencia del procesador es de 2 GHz, suponiendo que no hubiera atascos en el cauce se podría
alcanzar:
Vpico tasa de retirada F 2 2 109 4 109 instrucciones/s
13. Suponga un procesador superescalar en que se captan y decodifican dos instrucciones por
ciclo, se emiten tres instrucciones por ciclo como máximo (con emisión desordenada y no
alineada, sin estaciones de reserva), y se retiran hasta dos instrucciones por ciclo como
máximo. La emisión y la ejecución son desordenadas, y las instrucciones, una vez
decodificadas, se introducen en un búfer de reordenamiento (ROB) que permite la
finalización ordenada del procesamiento de las instrucciones.
a) Indique las dependencias entre instrucciones, los ciclos en los que se emiten
las instrucciones para su ejecución y cómo evolucionaría el búfer de
reordenamiento hasta que se hayan retirado todas las instrucciones de la
siguiente secuencia de instrucciones almacenadas en la cola de instrucciones
captadas:
NOTA: La suma y la resta consumen dos ciclos de reloj y la multiplicación cuatro ciclos. Considere
que no hay limitaciones en la capacidad de los búferes, pero sólo tiene un multiplicador y dos
sumadores/restadores. Se supone que f1, f2, y f3 tienen valores válidos previos.
Solución
Ya que el procesador no dispone de estaciones de reserva, la lógica de emisión tiene que esperar a que
los operandos le sean facilitados por la lógica de bypass, por tanto, las dependencias RAW afectarán al
orden de emisión de las instrucciones. Por otro lado, como se pueden decodificar hasta dos
instrucciones por ciclo y emitir hasta tres, suponemos que cada una de estas tareas se realizarán en
etapas diferentes del cauce. Es decir, que la etapas serán IF para captar instrucciones, ID para
decodificarlas, EX para ejecutarlas, ROB para escribir los resultados en el ROB y WB para retirar las
instrucciones del cauce. La Figura 25 muestra una traza de la ejecución del fragmento de código del
enunciado en la que se muestra el número de ciclos que tarda en ejecutarse, el momento en que se
emite cada instrucción y los siguientes riesgos RAW entre instrucciones:
Las instrucciones (3), (5) y (6) dependen de la instrucción (1) por f1.
INSTRUCCIÓN 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
multd f1, f1, f2 IF ID EX ROB WB
addd f3, f3, f2 IF ID EX ROB WB
multd f4, f1, f3 IF ID EX ROB WB
addd f5, f4, f2 IF ID EX ROB WB
addd f3, f1, f3 IF ID EX ROB WB
subd f5, f2, f1 IF ID EX ROB WB
En cuanto a la evolución del ROB, la Tabla 12 muestra los cambios que se producen cada ciclo
resaltados en negrita:
En el ciclo 8 se retiran las instrucciones (1) y (2) y se escriben sus resultados en los
registros de la arquitectura.
número de ciclos 15
T 5 ns
F 3 109
Para la calcular la velocidad pico, como sólo se pueden retirar hasta dos instrucciones por ciclo,
tenemos:
NOTA: Considere que, conectadas a la estación de reserva para el acceso a memoria, tiene una
unidad funcional de carga con un retardo de dos ciclos y una de almacenamiento con retardo
de un ciclo; conectadas a la estación de reserva para enteros tiene dos ALU con retardo de
un ciclo; y, conectadas a la estación de reserva para coma flotante tiene una unidad de
multiplicación con tres ciclos de retardo y dos unidades de suma con dos ciclos de retardo.
No hay límite en el número de líneas de la cola de instrucciones y del ROB.
Solución
Suponiendo un envío desordenado para todas las estaciones de reserva, el código tardaría 25 ciclos en
ejecutarse, tal y como se muestra en la Figura 26. A continuación se describen las causas de los
retrasos de las instrucciones de la figura:
Como las estaciones de reserva tienen sólo tres entradas cada una, cuando alguna se
llena no permite que se puedan emitir más instrucciones hacia ella hasta que envíe
alguna instrucción y deje algún hueco. Este fenómeno se puede apreciar en la
instrucción (8), que no puede entrar hasta que se envía la instrucción (2) y se
quedan en la estación de reserva las instrucciones (4) y (5). También se crea un
cuello de botella en la estación de reserva de acceso a memoria con la instrucción
(10), que no puede emitirse hasta que se envía la instrucción (4), y que retrasa la
emisión de la instrucción (11), ya que la emisión es ordenada. Por último, la
instrucción (12) se bloqueará en la cola de instrucciones hasta que se envíe a
ejecutar la instrucción (5).
Por último, se producen riesgos RAW entre las instrucciones (2) - (3) por f2,
(3) - (4) por f4, (5) - (6) por f5, (6) - (7) - (8) por f6, (10) - (11) por f7, y (11) - (12)
por f8.
INSTRUCCIÓN 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
lf f3, 0(r1) IF ID EX ROB WB
lf f2, 8(r1) IF ID EX ROB WB
addf f4, f2, f3 IF ID EX ROB WB
sf 16(r1), f4 IF ID EX ROB WB
lf f5, 16(r2) IF ID EX ROB WB
addf f6, f5, f2 IF ID EX ROB WB
multf f6, f6, f4 IF ID EX ROB WB
sf 8(r2), f6 IF ID EX ROB WB
addi r3, r2, #32 IF ID EX ROB WB
lf f7, 0(r3) IF ID EX ROB WB
multf f8, f7, f3 IF ID EX ROB WB
sf 0(r3), f8 IF ID EX ROB WB
En el caso de que el envío fuese desordenado sólo para la estación de reserva de acceso a memoria, el
resultado sería exactamente el mismo, ya que debido a los riesgos del programa, todas las instrucciones
se han enviado ordenadamente.
15. En un programa, una instrucción de salto condicional (a una dirección de salto anterior) tiene
el siguiente comportamiento en una ejecución de dicho programa:
SSNNNSSNSNSNSSSSSN
donde S indica que se produce el salto y N que no. Indique la penalización efectiva que se
introduce si se utiliza:
NOTA: La penalización por saltos incorrectamente predichos es de 5 ciclos y para los saltos
correctamente predichos es 0 ciclos.
Solución
En el caso de usar predicción fija, se produciría un fallo del predictor cada vez que se tome el salto, tal
y como muestra la Tabla 13. Por tanto, la penalización total sería de:
Pfijo Ffijo P 11 5 55 ciclos
PREDICCIÓN N N N N N N N N N N N N N N N N N N
EJECUCIÓN S S N N N S S N S N S N S S S S S N
PENALIZACIÓN P P P P P P P P P P P
Si se usa el predictor estático, como la dirección de destino del salto es anterior, se producirá un fallo
en la predicción cuando no se produzca el salto, tal y como muestra la Tabla 14. Por tanto, la
penalización total sería de:
PREDICCIÓN S S S S S S S S S S S S S S S S S S
EJECUCIÓN S S N N N S S N S N S N S S S S S N
PENALIZACIÓN P P P P P P P
En cuanto al predictor dinámico con dos bits de historia, la Tabla 15 muestra el estado del predictor
antes de ejecutar el salto, la predicción que realiza el predictor, el comportamiento del salto y si se
produce o no penalización. Teniendo en cuanta los fallos que se producen, la penalización total sería
de:
ESTADO 11 11 11 10 01 00 01 10 01 10 01 10 01 10 11 11 11 11
PREDICCIÓN S S S S N N N S N S N S N S S S S S
EJECUCIÓN S S N N N S S N S N S N S S S S S N
PENALIZACIÓN P P P P P P P P P P P
Tabla 15. Comportamiento del predictor dinámico con dos bits de historia en el problema 15.
Por último, en la Tabla 16 se indican los bits de historia que existen antes de que se ejecute la
instrucción, la predicción que determinan esos bits, y lo que finalmente ocurre (según se indica en la
secuencia objeto del problema). La última fila indica si ha habido penalización (no coinciden la
predicción y lo que ocurre al final). Teniendo en canta esta información, tenemos que la penalización
total es de:
ESTADO 111 111 111 011 001 000 100 110 011 101 010 101 010 101 110 111 111 111
PREDICCIÓN S S S S N N N S S S N S N S S S S S
EJECUCIÓN S S N N N S S N S N S N S S S S S N
PENALIZACIÓN P P P P P P P P P P
Tabla 16. Comportamiento del predictor dinámico con tres bits de historia en el problema 15.
16. Un procesador utiliza un esquema de predicción dinámica de saltos de dos niveles similar al
del Pentium III: tres bits de historia se utilizan para indicar si en las tres últimas ejecuciones
de la instrucción hubo o no hubo salto, y esos tres bits de historia sirven de puntero a 8
contadores de dos bits, cada uno de los cuales se utiliza para realizar la predicción
correspondiente según su estado como en un esquema de predicción de dos bits. En la
primera ejecución, los tres bits que apuntan a los contadores de dos bits están a 000 y los bits
de los contadores de dos bits se inicializan a 00 (predice no saltar) si la instrucción de salto es
hacia adelante y a 11 (predice saltar) si el salto es hacia atrás. Si la predicción es correcta no
hay penalización, pero si es incorrecta, la penalización es de cuatro ciclos.
NOTA: La instrucción 1 salta hacia atrás y las instrucciones 2 y 3 saltan hacia adelante.
Solución
Como para cada instrucción de salto se utiliza un contador y unos bits de estado independientes del
resto de los saltos, consideraremos cada una de las instrucciones de salto por separado. Así, para la
primera instrucción tenemos el comportamiento N1 N1 N1 S1, para la segunda S2 N2 S2 S2, y para la
tercera N3 S3 N3 N3.
La Tabla 17 muestra el comportamiento del predictor, así como la evolución de los bits de historia que
se usan para cada salto a lo largo de la ejecución del código. Con ayuda de esta tabla tenemos que en la
ejecución del primer salto se producen tres fallos, en la del segundo otros tres, y en la del tercero una
más, por lo que la penalización total obtenida es de:
17. Un procesador utiliza un esquema de predicción dinámica de saltos de dos niveles similar al
del Pentium III: tres bits de historia se utilizan para indicar si en las tres últimas ejecuciones
de la instrucción hubo o no hubo salto, y esos tres bits de historia sirven de puntero a 8
contadores de dos bits, cada uno de los cuales se utiliza para realizar la predicción
correspondiente, según su estado, como en un esquema de predicción dinámica de dos bits.
En la primera ejecución, los tres bits que apuntan a los contadores de dos bits están a 000 y
los bits de los contadores de dos bits se inicializan a 00 (predice no saltar) si la instrucción de
salto es hacia adelante, y a 11 (predice saltar) si el salto es hacia atrás. Si la predicción es
correcta no hay ciclos de penalización y si es incorrecta hay cuatro ciclos.
¿Cual es la penalización para el bucle que se indica a continuación, para 1 < d < 8?
etiqueta:
Compárelo con un esquema de predicción estática que predice saltar si el salto es hacia atrás
y no saltar si el salto es hacia adelante.
Solución
Una vez traducido el código a ensamblador tendría un aspecto similar a este:
bucle: …
saltar a etiqueta ; S1
saltar a bucle ; S2
etiqueta: …
En este código hay dos saltos, que a partir de ahora notaremos como S1 y S2 (si saltan) o N1 y N2 (si
no saltan). Para valores de d tales que 1 < d < 8 el patrón de saltos del código es:
N 1S 2 8d S1
es decir, que el salto del bucle siempre se va a tomar y el salto hacia delante no se tomará nunca
excepto la última vez, en la que se saldrá del bucle y continuará hacia delante. Como tenemos un
predictor dinámico de dos niveles, para cada salto habrá un conjunto de 8 contadores de dos bits, que
se inicializarán a 00 para el salto hacia delante y a 11 para el salto hacia atrás, y se seleccionará uno de
estos 8 contadores para hacer la predicción en función del los 3 bits de historia (según el
comportamiento del salto en las últimas tres iteraciones).
SALTO ITERACIONES 1 2 3 4 ÚLTIMA
Según la Tabla 18, en la última iteración el salto S2 no se llega a ejecutar, ya que se sale del bucle por el
salto S1. Los predictores aciertan en el comportamiento del salto hacia atrás, que se toma todas las
veces, y en todas las ejecuciones del salto hacia adelante menos en la última, por lo que sólo se
equivocan una vez. Por tanto, la penalización total es de:
En el caso de que el mecanismo de predicción fuera estático, se usaría el mismo predictor para todos
los saltos. Este predictor, según el enunciado del problema, realizaría la siguiente predicción:
N 1S 2 8d N 1
Pestático F P 1 4 4 ciclos
etiqueta:
Indique cuál es la penalización efectiva debida a los saltos, en función del valor inicial de c
(número entero), considerando que el procesador utiliza:
NOTA: La penalización por saltos incorrectamente predichos es de 4 ciclos y para los saltos
correctamente predichos es 0 ciclos.
Solución
Al igual que en el ejercicio anterior, al traducir el fragmento de código a ensamblador se codificarán
dos saltos: S1, que estará dentro del bucle y saltará hacia etiqueta, y S2, que será el salto al final del bucle
para iniciar otra iteración. Dependiendo del valor inicial de c se pueden distinguir tres
comportamientos diferentes de los saltos:
N 1S 2 9 N 1 N 2
2. 1 ≤ c < 10:
Si c = 9: N 1S 2 S1
Si c = 8: N 1S 2 2 S1
…
Si c = 1: N 1S 2 9 S1
Es decir:
N 1S 2 10 c S1
3. c ≥ 10:
S1
Una vez obtenidos los comportamientos de los saltos correspondientes a los distintos valores posibles
de c, se pasa a considerar cada uno de los esquemas de predicción indicados. Para el caso de un
predictor fijo que esté diseñado para predecir que siempre se va a tomar el salto tendríamos las
siguientes penalizaciones en función del valor de c:
En el segundo apartado del problema se nos pide que estimemos la penalización en el caso de usar un
predictor estático que suponga que los saltos hacia atrás se tomarán siempre y los saltos hacia adelante
no se tomarán nunca. Dependiendo del valor de c tendremos:
Por consiguiente, para cualquier valor de c, este esquema de predicción siempre da lugar a 4 ciclos de
penalización.
El último esquema de predicción que se propone en este ejercicio es un predictor dinámico con un bit
de historia. En este caso, al tratarse de un esquema dinámico, habrá un predictor para cada salto, cuyo
bit de historia estará inicializado a 1, e irá cambiando a 1 ó 0 en función de la última ejecución del salto
(1 si saltó y 0 si no lo hizo). En función del valor de c tendremos:
Una vez que hemos determinado la penalización de la secuencia para cada tipo de predictor, podemos
pasar a resolver la última cuestión del problema dada la distribución de probabilidad de la variable c
que se da en el enunciado. Para el caso del predictor fijo, y teniendo en cuenta que todos los valores
de c entre 1 y 9 son equiprobables, tenemos:
9
c 1
10 c 4
Pfijo 0.25 Pfijo1 0.45 Pfijo 2 0.30 Pfijo 3 0.25 44 0.45 0.30 0 20 ciclos
9
Pestático 0.25 Pestático1 0.45 Pestático2 0.30 Pestático3 0.25 4 0.45 4 0.30 4 4 ciclos
Pdinámico 0.25 Pdinámico1 0.45 Pdinámico2 0.30 Pdinámico3 0.25 8 0.45 8 0.30 0 5.6 ciclos
Como se puede ver, para este bucle, y para la distribución de probabilidad de los valores de c, el
esquema de predicción más eficiente corresponde a la predicción estática. No obstante, como se ha
visto, esta situación depende de las probabilidades de los distintos valores de c. Si, por ejemplo, la
probabilidad de que c esté entre 1 y 9 fuera de 0.15, la penalización para la predicción dinámica con 1
bit de historia sería de 3.2 ciclos, mientras que la predicción estática seguiría presentando una
penalización de 4 ciclos.
NOTA: La penalización por saltos incorrectamente predichos es de 4 ciclos y para los saltos
correctamente predichos es 0 ciclos. Para hacer la predicción en la primera ejecución de la
instrucción de salto se utiliza un esquema de predicción estática (salta si el salto es hacia atrás
y no salta si el salto es hacia adelante) y el estado inicial es 00 si se ha predicho no saltar y 11
si se ha predicho saltar.
Solución
En la secuencia de instrucciones del problema aparecen tres saltos, que a partir de ahora notaremos
coma S1, S2 y S3 como se muestra a continuación:
El salto S1 controla el contador ascendente r2, que se inicializa con el valor dato y
que provoca la salida del bucle cuando r2 alcanza el valor 4 (siempre que dato haya
sido inicializado a un valor menor o igual que 4).
El salto S2 controla el contador descendente r5, que se inicializa con el valor dato y
que provoca la salida del bucle cuando r5 alcanza el valor 0.
SALTO 1 N N N N N S N S S N N N N
SALTO 2 S N S N N – N – – N N N N
SALTO 3 – S – S S – S – – S S S N
Dependiendo del valor de dato, los saltos se comportarán según indica la Tabla 19, lo que se puede
resumir en los siguientes tres casos:
1. Si dato < 2:
S1: N dato + 1.
S2: N dato S.
S3: S dato.
2. Si 2 ≤ dato ≤ 4:
S1: N 4 – dato S.
S2: N 4 – dato.
S3: S 4 – dato.
3. Si dato > 4:
S1: N 4.
S2: N 4.
S3:. S 3 N
Una vez obtenidos estos casos, podemos pasar a estudiar el comportamiento del predictor:
1. Si dato < 2, el predictor estático acertará la primera vez para cada uno de los tres
saltos, inicializando los bits de estado de S1 a 00, de S2 a 00 y de S3 a 11. Como
después de esta inicialización todos los saltos repiten su comportamiento hasta el
final excepto S2, que es el que provoca la salida del bucle, todos los saltos serán bien
predichos a excepción del último salto de S2, con lo que la penalización total de de
1 fallo, es decir, 4 ciclos.
2. Si 2 ≤ dato ≤ 4, el predictor estático acertará la primera vez para cada uno de los
tres saltos, como pasaba en el caso anterior. Como después de esta inicialización
todos los saltos repiten su comportamiento hasta el final excepto S1, que es el que
provoca la salida del bucle, todos los saltos serán bien predichos a excepción del
último salto de S1, con lo que la penalización total de de 1 fallo, es decir, 4 ciclos.
3. Si dato > 4, el predictor estático también acertará la primera vez para cada uno de
los tres saltos. Como después de esta inicialización todos los saltos repiten su
comportamiento hasta el final excepto S3, que es el que provoca la salida del bucle,
todos los saltos serán bien predichos a excepción del último salto de S3, con lo que
la penalización total de de 1 fallo, es decir, 4 ciclos.
Como conclusión podemos decir que independientemente del valor de la variable dato, la secuencia de
instrucciones tiene una penalización de 4 ciclos debida a los saltos.
20. Disponemos del siguiente código DLX:
lw r9, n ; (1)
add r10, r0, r0 ; (2)
inicio: lw r1, a(r10) ; (3)
sgt r2, r1, r0 ; (4)
bnez r2, mayor ; (5)
sub r1, r0, r1 ; (6)
beqz r2, fin ; (7)
mayor: add r1, r1, r1 ; (8)
fin: sw r1, a(r10) ; (9)
addi r10, r10, #1 ; (10)
seq r3, r9, r10 ; (11)
bnez r3, inicio ; (12)
trap #0 ; (13)
Solución
En la secuencia de instrucciones del problema aparecen tres saltos, que a partir de ahora notaremos
como S1, S2 y S3 como se muestra a continuación:
lw r9, n
add r10, r0, r0
inicio: lw r1, a(r10)
sgt r2, r1, r0
bnez r2, mayor ; (S1)
sub r1, r0, r1
beqz r2, fin ; (S2)
mayor: add r1, r1, r1
fin: sw r1, a(r10)
addi r10, r10, #1
seq r3, r9, r10
bnez r3, inicio ; (S3)
trap #0
Teniendo en cuenta el comportamiento del predictor estático descrito en el enunciado y que solo el
10% de los valores del vector a son positivos, podemos descubrir que:
El salto S2 saltará hacia adelante el 90% de las iteraciones (siempre que se ejecute y
no se haya saltado en S1), y cuando salte incurrirá en una penalización de 5 ciclos.
El salto S3 controla el bucle, con lo que saltará hacia atrás en todas las iteraciones
excepto en la última, provocando una penalización de 5 ciclos.
Por tanto, para un vector a de tamaño n, la penalización debida a los saltos mal predichos será:
Tras esto podemos darnos cuenta de que el salto S2 está mal predicho todas las veces que se ejecuta
(90% de las iteraciones), así que haciendo uso de las nuevas instrucciones de salto para cambiar la
predicción, deberíamos sustituirlo por la siguiente instrucción:
Esta instrucción cambia el comportamiento del predictor estático y hace que no se equivoque nunca,
con lo que con esta mejora la penalización se reduce a:
n 10
P F1 F2 F3 P 0.1n 1 5 ciclos
2
Con este resultado podemos concluir que este cambio nos reduce la penalización debida saltos mal
predichos en casi un 90%.
lw r1, N ; (1)
add r2, r0, r0 ; (2)
bucle: lw r3, X(r2) ; (3)
sgt r4, r3, r0 ; (4)
bnz r4, mayor ; (5)
sub r3, r0, r3 ; (6)
mayor: sw X(r2), r3 ; (7)
add r2, r2, #4 ; (8)
sub r1, r1, #1 ; (9)
bnz r1, bucle ; (10)
Si el procesador usa un predictor dinámico con dos bits de historia que se inicializan con un
predictor estático que predice como tomados los saltos hacia atrás y como no tomados los
saltos hacia delante, y que la penalización en caso de errar la predicción es de 5 ciclos, ¿qué
penalización se obtendrá si X(0) = 1 y X(i + 1) = 1 – X(i)? ¿Qué penalización se obtendría si
se optimizara el código usando sentencias de ejecución condicional?
Solución
El programa del enunciado calcula el valor absoluto de los elementos del vector X. Va procesándolos
de uno en uno y les cambia el signo si no son positivos. Consta de dos saltos, el primero de ellos, al
que notaremos como S1 en el código de más abajo, sirve para detectar si los números son positivos y
el segundo, notado como S2, se emplea para volver a ejecutar el código mientras queden elementos
por procesar en el vector X.
lw r1, N
add r2, r0, r0
bucle: lw r3, X(r2)
sgt r4, r3, r0
bnz r4, mayor ; (S1)
sub r3, r0, r3
mayor: sw X(r2), r3
add r2, r2, #4
sub r1, r1, #1
bnz r1, bucle ; (S2)
Para cada uno de los dos saltos, sus bits de historia se inicializarán según el predictor estático del
computador, que predice como tomados los saltos hacia atrás. Por tanto, los bits de historia de S1 se
iniciarán al valor 00, ya que es un salto hacia delante, y los de S2 al valor 11 porque salta hacia atrás.
Una vez inicializados los bits de historia, la penalización que introduzca cada uno de ellos dependerá
del comportamiento de cada salto. En el caso de S1, su comportamiento está determinado por el valor
de cada elemento del vector X. S1 saltará siempre que X(i) sea mayor que cero, y según el enunciado,
el vector X es de la forma X = {1, 0, 1, 0, 1, 0,…}, por lo que S1 saltará una vez sí y otra no hasta que
se termine de procesar el vector X. El salto S2 saltará tantas veces como elementos tenga el vector X
menos una, es decir N – 1 veces, ya que el programa se dedica a procesar dicho vector. Teniendo esto
en cuenta, el comportamiento del predictor será el que indica la Tabla 20.
ITERACIÓN 0 1 2 3 … N–1 N
VALOR DE X 1 0 1 0 … 0 1
SALTO 1 BITS DE HISTORIA 00 01 00 01 … 01 00
PREDICCIÓN N N N N … N N
EJECUCIÓN S N S N … N S
PENALIZACIÓN P P … P
SALTO 2 BITS DE HISTORIA 11 11 11 11 … 11 11
PREDICCIÓN S S S S … S S
EJECUCIÓN S S S S … S N
PENALIZACIÓN … P
N
Poriginal F1 F2 P 1 5 ciclos
2
Está claro que el comportamiento de S1 no puede ser aprendido por el predictor dinámico, por lo que
nos va a ocasionar muchas faltas, así que sería interesante cambiarlo por una sentencia de ejecución
condicional, tal y como muestra el siguiente código:
lw r1, N
add r2, r0, r0
bucle: lw r3, X(r2)
sub r4, r0, r3
cmov.gt r4, r3, r3
sw X(r2), r4
add r2, r2, #4
sub r1, r1, #1
bnz r1, bucle
En esta versión mantenemos el mismo número de instrucciones para ejecutar el algoritmo, y además
evitamos el salto S1, que depende del valor de cada componente de X, por lo que la penalización total
del programa es de:
Poptimización F2 P 1 5 5 ciclos
22. Se dispone de un procesador superescalar capaz de captar, decodificar y retirar hasta dos
instrucciones por ciclo, con una única ventana de instrucciones con emisión desordenada y
no alineada, búfer de reordenamiento para el renombrado y la finalización ordenada, y una
latencia de dos ciclos para las instrucciones de carga de memoria y de un ciclo para las
instrucciones aritméticas con enteros y los almacenamientos. Se desea ejecutar el siguiente
programa en el procesador:
lw r1, n
lw r2, a
add r3, r0, r0
bucle: add r3, r3, r2
subi r1, r1, #1
bnez r1, bucle
sw r3, b
trap #0
NOTA: Suponga que hay tantas unidades de ejecución y de acceso a memoria como sea necesario.
Solución
La Figura 27 muestra una traza de ejecución del programa. La primera vez que se capta el salto se usa
el predictor estático, que no puede realizar la predicción hasta que se decodifica la instrucción. Por
tanto, se introduce una penalización de un ciclo, ya que mientras que se decodifica el salto entran en el
cauce las instrucciones sw y trap que se deben anular en el momento en el que se predice que el salto se
va a realizar (cuando se retiren no se modificarán los registros de la arquitectura).
En la etapa de ejecución del salto se comprueba que la predicción ha sido correcta y se procede a la
inicialización del predictor dinámico creando una entrada en el BTB para estas instrucción de salto
con el estado 11 (saltar). A partir de ahora, todas las veces que se capte el salto, se captará junto con la
instrucción siguiente (sw), ya que las instrucciones se captan de dos en dos. En la etapa de captación se
consultará el BTB y se descubrirá que la instrucción captada es un salto con una predicción de saltar,
así que se anulará la instrucción sw y se comenzará a captar en el ciclo siguiente a partir de la
instrucción de destino del salto.
En la mayoría de los casos se acertará la predicción del salto, ya que se supone que un bucle va a iterar
bastantes veces. Sin embargo, en este problema el bucle sólo tiene que iterar n = 2 veces, así que en la
segunda iteración el predictor dinámico fallará. El procesador no se da cuenta del fallo de la
predicción hasta que el salto termina la etapa EX, en la que se calcula la condición del salto. En este
momento se anulan todas las instrucciones captadas especulativamente y se fija el contenido de PC a
la instrucción del camino secuencial. En total se pierden 2 ciclos. Tras introducir las instrucciones sw y
trap en el cauce, se sigue su ejecución hasta que se retiran en el ciclo 13, momento en el que finaliza la
ejecución del programa.
INSTRUCCIÓN 1 2 3 4 5 6 7 8 9 10 11 12 13
lw r1, n IF ID EX ROB WB
lw r2, a IF ID EX ROB WB
add r3, r0, r0 IF ID EX ROB WB
add r3, r3, r2 IF ID EX ROB WB
subi r1, r1, #1 IF ID EX ROB WB
bnez r1, bucle IF ID EX ROB WB
sw r3, b IF Flush
trap #0 IF Flush
add r3, r3, r2 IF ID EX ROB WB
subi r1, r1, #1 IF ID EX ROB WB
bnez r1, bucle IF ID EX ROB WB
sw r3, b IF Flush
add r3, r3, r2 IF Flush
subi r1, r1, #1 IF Flush
bnez r1, bucle IF Flush
sw r3, b IF Flush
sw r3, b IF ID EX ROB WB
trap #0 IF ID EX ROB WB
PENALIZACIÓN P P P
Analizado la traza del programa, podemos deducir que la penalización introducida por el predictor
estático es de:
Pdin_fallo = 2 ciclos (al igual que el predictor estático, no se corrige hasta después de
la etapa de ejecución).
Por tanto, como el bucle itera n veces, la primera iteración se predice con el predictor estático, y el
resto con el dinámico, la expresión general para calcular su penalización es:
ya que se acertarán todas las predicciones excepto la de la última iteración, en la que se predecirá saltar
y se fallará. Esta penalización se producirá en cualquier ejecución del bucle, independientemente del
valor de n.
23. Suponga un procesador superescalar en que se captan, decodifican, emiten y retiran hasta dos
instrucciones por ciclo. La etapa de decodificación se realiza de forma ordenada, ya que es en
esta etapa donde se introducen las instrucciones en un búfer de reordenamiento (ROB) que
permite su finalización ordenada. Por el contrario, la emisión es desordenada y se
implementa mediante estaciones de reserva individuales para cada unidad funcional. El
procesador utiliza predicción dinámica de saltos con dos bits de historia. Para la primera
ejecución de una instrucción de salto dada, el procesador predice saltar si la dirección de salto
es hacia direcciones inferiores, y no saltar si la dirección es mayor. Las instrucciones de salto
se procesan en la etapa de ejecución y consumen un ciclo en esa etapa (en el siguiente ciclo
ya se tendría la dirección de salto correcta y se podría captar la instrucción correcta si la
predicción de salto no hubiera sido correcta).
Suponiendo una frecuencia de 2 GHz, que el cauce se encuentra inicialmente vacío, y que
inicialmente r2 = 100000, para la siguiente secuencia de instrucciones:
NOTA: La instrucción loop decrementa el registro y salta si el valor del registro es distinto de cero. La
suma y la resta en coma flotante consumen dos ciclos de reloj y la multiplicación en coma
flotante cuatro ciclos. Considere que no hay limitaciones en la capacidad de los búferes y en
el número de unidades funcionales. Se supone que todos los registros tienen valores válidos
previos.
Solución
Para responder al primer apartado es necesario realizar una traza de su ejecución. En la Figura 28 se
muestra una traza en la que se supone que r2 = 3 iteraciones. En esta traza se observan los riesgos de
control:
La primera vez que se capta el salto, no se puede usar el predictor dinámico porque
no existe ninguna entrada en el BTB del procesador para él. Por tanto, en la etapa
de decodificación, una vez que se identifique el salto, se incluirá una entrada en el
BTB para que la siguiente vez que se capte se pueda usar el predictor dinámico, se
usará un predictor estático que predecirá saltar (el salto es hacia atrás), y se anularán
las dos instrucciones que se captaron erróneamente tras el salto. Teniendo en
cuenta las etapas del cauce, el predictor estático provocará una penalización de 1
ciclo para los saltos acertados.
A partir de la segunda iteración, cada vez que se capte el salto se usará el predictor
dinámico, por lo que no hay penalización en caso de acertar. Esto ocurrirá en el
resto de iteraciones menos en la última, en la que el predictor fallará y obtendremos
una penalización de 2 ciclos hasta captar la siguiente instrucción al salto, ya que es
en la etapa de ejecución en la que se comprueba la corrección de la predicción. Una
vez que se comprueba que falló la predicción, se anulan todas las instrucciones
captadas especulativamente y se comienza a captar desde la dirección correcta para
terminar la ejecución del programa.
Estos ciclos de penalización se solapan con los introducidos por los riesgos RAW entre las sucesivas
iteraciones del bucle a causa de f6 y f5, por lo que al final no influyen en el tiempo de ejecución, que
está determinado por los riesgos RAW existentes en el código.
INSTRUCCIÓN 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
addd f1, f1, f6 IF ID EX ROB WB
multd f6, f2, f5 IF ID EX ROB WB
subd f5, f1, f3 IF ID EX ROB WB
loop r2, bucle IF ID EX ROB WB
addd f7, f1, f5 IF Flush
Sig. instrucción IF Flush
addd f1, f1, f6 IF ID EX ROB WB
multd f6, f2, f5 IF ID EX ROB WB
subd f5, f1, f3 IF ID EX ROB WB
loop r2, bucle IF ID EX ROB WB
addd f1, f1, f6 IF ID EX ROB WB
multd f6, f2, f5 IF ID EX ROB WB
subd f5, f1, f3 IF ID EX ROB WB
loop r2, bucle IF ID EX ROB WB
addd f1, f1, f6 IF ID Flush
multd f6, f2, f5 IF ID Flush
subd f5, f1, f3 IF ID Flush
loop r2, bucle IF ID Flush
addd f7, f1, f5 IF ID EX ROB WB
PENALIZACIÓN P P P
Si nos fijamos en el instante de tiempo en el que se retira la última instrucción del bucle en cada
iteración, podemos estimar que una vez terminada la primera iteración tras un tiempo TLI, el resto de
iteraciones irán terminando cada MLM ciclos, y una vez terminada la ejecución del bucle, la última
instrucción tardará un ciclo más en ejecutarse. Por tanto, para un número de iteraciones N, y teniendo
en cuenta que la frecuencia del procesador es de 2 GHz, podemos concluir que el tiempo de ejecución
es de:
Para contestar al segundo apartado, como el procesador puede completar hasta 2 instrucciones por
ciclo, su velocidad pico es de:
F
Rpico IPC F 2 2 109 4 109 instrucciones/s
CPI
24. Se dispone de un procesador superescalar capaz de captar, decodificar y retirar hasta cuatro
instrucciones por ciclo, con una única ventana de instrucciones con emisión centralizada,
desordenada y no alineada, y con un búfer de reordenamiento para el renombrado y la
finalización ordenada. El procesador utiliza un predictor de saltos dinámico de dos bits que
se consulta en el momento de captar las instrucciones, de forma que si la dirección de
memoria de la que se está captando una instrucción se encuentra en el BTB, y la predicción
es saltar, guarda el contenido actual de PC y se cambia por la dirección de destino del salto
para que se empiece a captar desde ahí en el siguiente ciclo. Cuando la instrucción de salto
entra en el búfer de reordenamiento tras la decodificación, se marca con un bit pred = 1 si el
predictor decidió tomar el salto o pred = 0 en caso contrario. Posteriormente, cuando se
resuelve la condición del salto en la etapa de ejecución, se comprueba si la predicción se
realizó con éxito, y en caso contrario, se marcan con flush = 1 todas aquellas instrucciones
que se han introducido en el cauce de forma especulativa para que no actualicen los registros
al ser retiradas, y se fija PC al valor guardado en el momento de la predicción para continuar
con la siguiente instrucción en el siguiente ciclo. La primera vez que se capta un salto,
obviamente no se encuentra en el BTB, por lo que no se podrá predecir su comportamiento
hasta la etapa de decodificación, en la que se emplea un predictor estático que predice como
tomados todos los saltos hacia atrás y crea una entrada en el BTB para los saltos
encontrados. Si en el procesador descrito se ejecuta el siguiente programa:
lw r1, N ; (1)
lw r2, X ; (2)
add r3, r0, r0 ; (3)
bucle: add r3, r3, r2 ; (4)
add r4, r3, r3 ; (5)
subi r1, r1, #1 ; (6)
bnez r1, bucle ; (7)
sw R, r4 ; (8)
trap #0 ; (9)
NOTA: Suponga un número de unidades de ejecución y un tamaño de búferes suficiente como para
que no se provoquen riesgos estructurales en el cauce. Las unidades funcionales de acceso a
memoria tienen una latencia de 2 ciclos y el resto de unidades funcionales utilizadas 1 ciclo
de latencia.
Solución
Para responder a la primera pregunta es necesario entender el funcionamiento del programa, que
básicamente consiste en lo siguiente:
r 3i r 3i 1 X
r 4i 2 r 3i
siendo i el número de iteraciones que se ejecutan y r3(0) = 0. Reescribiendo las expresiones anteriores
de forma que no se calculen de forma recursiva tenemos que:
r 3i i X
r 4 i 2 i X
Como el número de iteraciones del programa está controlado por el registro r1, que inicialmente se fija
al valor de la variable N, el valor final para R es de:
R r 4N 2 N X 2 3 3 18
Para responder a la siguiente cuestión usaremos la traza de la ejecución del programa, mostrada en la
Figura 29. En este diagrama se puede comprobar que el predictor estático (que se aplica en la etapa de
decodificación la primera vez que se capta un salto) introduce un ciclo de penalización para los saltos
tomados. El resto de las iteraciones que se ejecute el salto se usará el predictor dinámico, que no
introduce penalización en caso de acertar. Sin embargo, en la última iteración el predictor dinámico
falla. El fallo se detecta en la etapa de ejecución del salto, por lo que se introduce una penalización de
tres ciclos.
INSTRUCCIÓN 1 2 3 4 5 6 7 8 9 10 11 12 13 14
lw r1, N IF ID EX EX ROB WB
lw r2, X IF ID EX EX ROB WB
add r3, r0, r0 IF ID EX ROB WB
add r3, r3, r2 IF ID EX ROB WB
add r4, r3, r3 IF ID EX ROB WB
subi r1, r1, #1 IF ID EX ROB WB
bnez r1, bucle IF ID EX ROB WB
sw R, r4 IF ID Flush
trap #0 IF Flush
Sig. instrucción IF Flush
Sig. instrucción IF Flush
Sig. instrucción IF Flush
add r3, r3, r2 IF ID EX ROB WB
add r4, r3, r3 IF ID EX ROB WB
subi r1, r1, #1 IF ID EX ROB WB
bnez r1, bucle IF ID EX ROB WB
add r3, r3, r2 IF ID EX ROB WB
add r4, r3, r3 IF ID EX ROB WB
subi r1, r1, #1 IF ID EX ROB WB
bnez r1, bucle IF ID EX ROB WB
add r3, r3, r2 IF ID EX Flush
add r4, r3, r3 IF ID Flush
subi r1, r1, #1 IF ID EX Flush
bnez r1, bucle IF ID Flush
add r3, r3, r2 IF ID Flush
add r4, r3, r3 IF ID Flush
subi r1, r1, #1 IF ID Flush
bnez r1, bucle IF ID Flush
add r3, r3, r2 IF Flush
add r4, r3, r3 IF Flush
subi r1, r1, #1 IF Flush
bnez r1, bucle IF Flush
sw R, r4 IF ID EX EX ROB WB
trap #0 IF ID EX ROB WB
PENALIZACIÓN P P P P
Por último, para calcular el tiempo de ejecución para N iteraciones hay que tener en cuenta que
transcurren 8 ciclos hasta que se termina la primera iteración, que cada iteración termina un ciclo
después de la anterior, y que tras la última iteración hay que añadir 4 ciclos para almacenar el resultado
final, es decir, que el tiempo para ejecutar N iteraciones se puede calcular mediante las expresión:
Por tanto, para ejecutar N = 500 iteraciones serían necesarios 511 ciclos.
25. Se dispone de un procesador superescalar en el que se pueden captar y decodificar hasta dos
instrucciones por ciclo. Este ordenador cuenta con dos sumadores de latencia 2 ciclos, un
multiplicador de latencia 4 ciclos, y una unidad de carga con una latencia de 1 ciclo si se
produce un acierto en la cache o 3 ciclos si el dato solicitado no se encuentra en la cache.
Cada unidad de ejecución cuenta con su propia estación de reserva de 3 entradas. Para
mantener la consistencia secuencial y garantizar un tratamiento preciso de las interrupciones,
las instrucciones se introducen en un búfer de reordenamiento en la etapa de decodificación,
del que se retiran de dos en dos de manera ordenada una vez han terminado su ejecución. En
dicho procesador se pretende ejecutar el siguiente fragmento de código (que ya está alojado
en la cache de instrucciones):
Solución
La Figura 30 muestra una traza de la ejecución del programa. Hasta el ciclo 4, la ejecución del
programa es normal, las instrucciones se van captando, decodificando, etc., pero justo en este ciclo (el
segundo ciclo de la ejecución de la carga) se produce una excepción, por lo que se marca la instrucción
(2) con el campo excep = 1 y las instrucciones (2) – (5) con el campo flush = 1 como muestra la Tabla
21. A partir de este momento se dejan de captar instrucciones y se continúa la ejecución de las
instrucciones que hay en el cauce hasta que la instrucción que ha provocado la excepción alcance el
tope del búfer de reordenamiento.
En el ciclo 9, tras retirar todas las instrucciones marcadas con flush = 1, se salvará la dirección de la
instrucción load para poder reiniciar la ejecución del programa una vez se haya traído la página a
memoria, y se comenzará a captar instrucciones de la Rutina de Servicio de Interrupción (RSI),
suponiendo que no hay ningún retardo para obtener la su dirección. Como la RSI tarda 237 ciclos,
habrá terminado en el ciclo 245. Su última instrucción será un retorno de interrupción, que modifica el
registro PC con la dirección previamente guardada, así que en el ciclo 246 se volverá a captar a partir
de la instrucción load, que ahora no cometerá la excepción porque el dato que quiere leer ya está en
memoria. Por tanto, al final el código tarda en ejecutarse 253 ciclos.
Tabla 21. Estado del ROB en el momento en el que se produce la excepción en el problema 25.
INSTRUCCIÓN 1 2 3 4 5 6 7 8 9 10 … 246 247 248 249 250 251 252 253
multd f4, f1, f2 IF ID EX ROB WB
ld f5, X(r3) IF ID EX Excepción
addd f2, f3, f1 IF ID Flush
addd f3, f4, f2 IF ID Flush
subd f2, f3, f5 IF Flush
Sig. instrucción IF Flush
1ª instr. RSI IF ID
2ª instr. RSI IF ID
3ª instr. RSI IF
4ª instr. RSI IF
...
ld f5, X(r3) IF ID EX ROB WB
addd f2, f3, f1 IF ID EX ROB WB
addd f3, f4, f2 IF ID EX ROB WB
subd f2, f3, f5 IF ID EX ROB WB