Capítulo 3
Capítulo 3
Capítulo 3
Procesamiento superescalar
Captación Cola de
instrucciones
(IF)
2 1 sub r6 r5 0 [r2] 1 –
0 mult r5 [r1] 1 [r5] 1 –
3 3 add r2 [r3] 1 [r1] 1 –
2 sub r5 [r4] 1 [r3] 1 –
1 sub r6 r5 0 [r2] 1 –
4 3 add r2 [r3] 1 [r1] 1 –
1 sub r6 r5 0 [r2] 1 –
6 1 sub r6 r5 0 [r2] 1 –
9
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.
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.
0 1 r2 50 1 0
1 1 r3 1200 1 1
2 1 r2 20 1 1
3 1 r1 – 0 1
… … … … … …
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.
3 mult r1 – 0
4 st – – 0
5 add r1 17 1
6 xor r1 – 0
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.
Cuando una instrucción llega al cauce se comprueba si hay información de ella en el BTB
buscando (asociativamente) si su dirección se encuentra en el campo correspondiente del
BTB. Si es la primera vez que se procesa la instrucción, no estará incluida en el BTB, por
lo que se tendrá que realizar una predicción estática del salto (por ejemplo una predicción
teniendo en cuenta si el salto es hacia atrás o hacia adelante), se le asignará una línea del
BTB y se inicializará convenientemente el campo de bits de historia teniendo en cuenta si
se ha acertado o no en la predicción. En el caso de que la instrucción de salto que entra en
el cauce ya esté incluida en el BTB, se realiza la predicción según los bits de historia y se
actualizan los mismos según se haya acertado o no en la predicción. La Figura 4
proporciona un ejemplo de diagrama de estados para un procedimiento de predicción
dinámica de salto basado en dos bits de historia. Existen cuatro posibles estados
correspondientes a las cuatro combinaciones de los dos bits de historia. A dos de esas
combinaciones se les asigna la predicción de salto tomado (Tomado Fuerte y Tomado
Débil) y a las otras dos la de salto no tomado (No Tomado Débil y No Tomado Fuerte).
Según se produzca el salto (T, salto tomado) o no (NT, salto no tomado), los arcos del
diagrama indican cómo cambiarán los bits de historia para realizar la predicción la
siguiente vez que llegue la instrucción de salto. Como se puede ver, mientras que se
acierta en la predicción se mantiene la misma, y sólo cuando se falla dos veces
consecutivas se cambia el sentido de ésta. Dada la importancia de disponer de un
esquema de predicción con elevados porcentajes de aciertos, ha habido un trabajo de
investigación bastante activo en este ámbito y se han propuesto una gran cantidad de
procedimientos de predicción con unos requisitos de memoria para los bits de historia
bastante considerables en muchos casos. En [ORT05] se puede completar la información
acerca de éstos.
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.
3 mult r1 – 0 0 0
4 st – – 0 1 1
5 add r1 17 1 0 1
6 xor r1 0xa1 1 0 1
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:
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
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.
Ciclo 3:
Se adelanta la ejecución de la instrucción (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.
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
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.
c) ¿Cuáles son los valores que quedan en los registros de la arquitectura al terminar,
si inicialmente f1 = 2.0 y f2 = 3.0?
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:
3 0 1 f1 2.0 1 1
1 1 f2 3.0 1 1
2 1 f3 – 0 1
4 0 1 f1 2.0 1 1
1 1 f2 3.0 1 0
2 1 f3 – 0 1
3 1 f2 – 0 1
5 0 1 f1 2.0 1 1
1 1 f2 3.0 1 0
2 1 f3 – 0 0
3 1 f2 – 0 1
4 1 f3 – 0 1
5 1 f5 – 0 1
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.
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:
3 0 1 f3 – 0 1
4 0 1 f3 – 0 0
1 1 f2 – 0 1
2 1 f3 – 0 1
5 0 1 f3 – 0 0
1 1 f2 – 0 1
2 1 f3 – 0 1
3 1 f5 – 0 1
6 0 1 f3 – 0 0
1 1 f2 – 0 1
2 1 f3 – 0 1
3 1 f5 – 0 1
4 1 f6 – 0 1
INSTRUCCIÓN 3 4 5 6 7 8 9 10 11 12 13 14
multd f3, f1, f2 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.
INSTRUCCIÓN 3 4 5 6 7 8 9 10 11 12
multd f3, f1, f2 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.
multd f3, f1, f2 ; (ciclo 2)
addd f2, f3, f1 ; (ciclo 2)
subd f3, f3, f1 ; (ciclo 3)
addd f4, f1, f2 ; (ciclo 3)
c) ¿Cuáles son los valores que quedan en los registros de la arquitectura al terminar,
si inicialmente f1 = 3.0 y f2 = 2.0?
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
2 0 multd f3 – 0
1 addd f2 – 0
3 0 multd f3 – 0
1 addd f2 – 0
2 subd f3 – 0
3 addd f4 – 0
7 0 multd f3 6.0 1
1 addd f2 – 0
2 subd f3 – 0
3 addd f4 – 0
8 1 addd f2 – 0
2 subd f3 – 0
3 addd f4 – 0
9 1 addd f2 9.0 1
2 subd f3 3.0 1
3 addd f4 – 0
10 3 addd f4 – 0
11 3 addd f4 12.0 1
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.
Teniendo en cuenta la evolución del ROB y las operaciones realizadas, los registros quedan al
final con los valores:
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.
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.
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:
2 0 lw r3 – 0
1 addi r2 – 0
2 add r1 – 0
3 lw r4 – 0
3 0 lw r3 – 0
1 addi r2 – 0
2 add r1 – 0
3 lw r4 – 0
4 lw r5 – 0
5 mult r6 – 0
6 add r5 – 0
7 add r6 – 0
4 0 lw r3 – 0
1 addi r2 128 1
2 add r1 0x0a 1
3 lw r4 – 0
4 lw r5 – 0
5 mult r6 – 0
6 add r5 – 0
7 add r6 – 0
8 sw – – 0
9 sw – – 0
10 sub r2 – 0
5 0 lw r3 [0x1a] 1
1 addi r2 128 1
2 add r1 0x0a 1
3 lw r4 – 0
4 lw r5 – 0
5 mult r6 – 0
6 add r5 – 0
7 add r6 – 0
8 sw – – 0
9 sw – – 0
10 sub r2 – 0
6 3 lw r4 [0x0a] 1
4 lw r5 [0x0a – 8] 1
5 mult r6 – 0
6 add r5 – 0
7 add r6 – 0
8 sw – – 0
9 sw – – 0
10 sub r2 112 1
7 5 mult r6 – 0
6 add r5 – 0
7 add r6 r4 + r3 1
8 sw – – 0
9 sw – – 0
10 sub r2 112 1
8 5 mult r6 – 0
6 add r5 – 0
7 add r6 r4 + r3 1
8 sw – – 1
9 sw – – 0
10 sub r2 112 1
9 5 mult r6 r5 × r3 1
6 add r5 – 0
7 add r6 r4 + r3 1
8 sw – – 1
9 sw – – 0
10 sub r2 112 1
10 6 add r5 r6 + r3 1
7 add r6 r4 + r3 1
8 sw – – 1
9 sw – – 0
10 sub r2 112 1
11 9 sw – – 1
10 sub r2 112 1
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
2 0 multd f1 – 0
1 addd f2 – 0
3 0 multd f1 – 0
1 addd f2 – 0
3 addd f4 – 0
4 addd f6 – 0
4 0 multd f1 – 0
1 addd f2 f2 + f5 1
3 addd f4 – 0
4 addd f6 – 0
5 multd f5 – 0
6 subd f6 – 0
6 0 multd f1 f1 × f5 1
1 addd f2 f2 + f5 1
3 addd f4 – 0
4 addd f6 – 0
5 multd f5 – 0
6 subd f6 – 0
7 3 addd f4 f1 + f2 1
4 addd f6 f1 + f5 1
5 multd f5 – 0
6 subd f6 f2 – f1 1
8 5 multd f5 f2 × f2 1
6 subd f6 f2 – f1 1
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:
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:
2 0 addd f1 – 0
1 multd f3 – 0
2 addd f6 – 0
3 0 addd f1 – 0
1 multd f3 – 0
2 addd f6 – 0
3 subd f4 – 0
4 0 addd f1 f1 + f4 1
1 multd f3 – 0
2 addd f6 – 0
3 subd f4 – 0
5 1 multd f3 – 0
2 addd f6 f1 + f4 1
3 subd f4 – 0
6 1 multd f3 – 0
2 addd f6 f1 + f4 1
3 subd f4 f1 – f6 1
8 1 multd f3 f1 × f2 1
2 addd f6 f1 + f4 1
3 subd f4 f1 – f6 1
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:
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
2 0 multd f1 – 0
1 addd f2 – 0
3 0 multd f1 – 0
1 addd f2 – 0
2 divd f4 – 0
3 addd f6 – 0
4 0 multd f1 – 0
1 addd f2 f2 + f5 1
2 divd f4 – 0
3 addd f6 – 0
4 multd f5 – 0
5 subd f6 – 0
6 0 multd f1 f1 × f5 1
1 addd f2 f2 + f5 1
2 divd f4 – 0
3 addd f6 – 0
4 multd f5 – 0
5 subd f6 – 0
7 2 divd f4 – 0
3 addd f6 f1 + f1 1
4 multd f5 – 0
5 subd f6 f2 – f1 1
8 2 divd f4 – 0
3 addd f6 f1 + f1 1
4 multd f5 f2 × f2 1
5 subd f6 f2 – f1 1
10 2 divd f4 f1 / f2 1
3 addd f6 f1 + f1 1
4 multd f5 f2 × f2 1
5 subd f6 f2 – f1 1
11 4 multd f5 f2 × f2 1
5 subd f6 f2 – f1 1
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:
V pico 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
Figura 25. Traza de la ejecución del código del problema 13.
2 0 multd f1 – 0
1 addd f3 – 0
3 0 multd f1 – 0
1 addd f3 – 0
2 multd f4 – 0
3 addd f5 – 0
4 0 multd f1 – 0
1 addd f3 – 0
2 multd f4 – 0
3 addd f5 – 0
4 addd f3 – 0
5 subd f5 – 0
5 0 multd f1 – 0
1 addd f3 f3 + f2 1
2 multd f4 – 0
3 addd f5 – 0
4 addd f3 – 0
5 subd f5 – 0
7 0 multd f1 f1 × f2 1
1 addd f3 f3 + f2 1
2 multd f4 – 0
3 addd f5 – 0
4 addd f3 – 0
5 subd f5 – 0
8 2 multd f4 – 0
3 addd f5 – 0
4 addd f3 – 0
5 subd f5 – 0
9 2 multd f4 – 0
3 addd f5 – 0
4 addd f3 f1 + f3 1
5 subd f5 f2 – f1 1
11 2 multd f4 f1 × f3 1
3 addd f5 – 0
4 addd f3 f1 + f3 1
5 subd f5 f2 – f1 1
12 3 addd f5 – 0
4 addd f3 f1 + f3 1
5 subd f5 f2 – f1 1
13 3 addd f5 f4 + f2 1
4 addd f3 f1 + f3 1
5 subd f5 f2 – f1 1
14 5 subd f5 f2 – f1 1
En cuanto a la evolución del ROB, la Tabla 12 muestra los cambios que se producen cada ciclo
resaltados en negrita:
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:
S S N N N S S N S N S N S S S S S N
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:
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:
1 1 1 1 0 0 0 1 0 1 0 1 0 1 1 1 1 1
ESTADO
1 1 1 0 1 0 1 0 1 0 1 0 1 0 1 1 1 1
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:
Tabla 16. Comportamiento del predictor dinámico con tres bits de historia en el problema 15.
Así, se puede indicar que la eficacia de un esquema de salto depende del perfil de saltos a que de
lugar la correspondiente instrucción de salto condicional. En la práctica, los esquemas de
predicción dinámica suelen funcionar mejor que los de predicción estática porque las instrucciones
de salto suelen repetir el comportamiento de su ejecución previa. En ese sentido, la secuencia
utilizada en este problema es bastante atípica.
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.
SALTO 1 ÚLTIMAS ITERACIONES 000 000 000 000
ESTADO DEL CONTADOR 11 10 01 00
PREDICCIÓN S S N N
EJECUCIÓN N N N S
PENALIZACIÓN P P P
SALTO 2 ÚLTIMAS ITERACIONES 000 100 010 101
ESTADO DEL CONTADOR 00 00 00 00
PREDICCIÓN N N N N
EJECUCIÓN S N S S
PENALIZACIÓN P P P
SALTO 3 ÚLTIMAS ITERACIONES 000 000 100 010
ESTADO DEL CONTADOR 00 00 00 00
PREDICCIÓN N N N N
EJECUCIÓN N S N N
PENALIZACIÓN P
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:
Ptotal F1 F2 F3 P 3 3 1 4 28 ciclos
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.
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 8 d S 1
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).
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:
Pdinámico F1 F2 P 1 0 4 4 ciclos
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 8 d N 1
Teniendo en cuenta el comportamiento del fragmento de código, el predictor estático sólo se
equivocaría en el último salto, con lo que volvemos a obtener una penalización de
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:
d) ¿Cuál de los tres esquemas anteriores es más eficaz por término medio si hay una
probabilidad del 25% de que c sea menor o igual a 0, una del 30% de que sea
mayor o igual a 10; y una del 45% de que sea cualquier número entre 1 y 9,
siendo todos equiprobables?
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:
1. c ≤ 0: El salto S1 no salta nunca y el salto S2 salta 9 veces (el bucle realiza 10 iteraciones,
el máximo de iteraciones del bucle):
N 1S 2 9 N 1N 2
2. 1 ≤ c < 10:
Si c = 9: N 1S 2 S 1
Si c = 8: N 1S 2 2 S 1
…
Si c = 1: N 1S 2 9 S 1
Es decir:
N 1S 2 10c 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:
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:
Pdinámico1 F1 F2 P 1 1 4 8 ciclos
2. 1 ≤ c < 10:
Pdinámico2 F1 F2 P 2 0 4 8 ciclos
Pdinámico3 0 0 P 0 ciclos
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
10 c 4
c1
Pfijo 0.25 Pfijo1 0.45 Pfijo2 0.30 Pfijo3 0.25 44 0.45 0.30 0 20 ciclo
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.
a) Indique cuál es la penalización efectiva debida a los saltos, en función del valor
inicial de dato (número entero mayor o igual que cero), considerando que el
procesador utiliza predicción dinámica con dos bits.
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:
addi r1, r0, #4
add r4, r0, r1
lw r2, dato
add r5, r2, r0
inicio: subi r3, r1, r2
beqz r3, final ; (S1)
addf f3, f2, f1
beqz r5, final ; (S2)
addf f3, f2, f1
addi r2, r2, #1)
subi r5, r5, #1)
subi r4, r4, #1
bnez r4, inicio ; (S3)
final:
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).
DATO 0 1 2 3 4 > 4
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.
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 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%.
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
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
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.
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
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
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:
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
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
R pico IPC F 2 2 109 4 109 instrucciones/s
CPI
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)
Solución
Para responder a la primera pregunta es necesario entender el funcionamiento del programa, que
básicamente consiste en lo siguiente:
r 3 i r 3 i 1 X
r 4 i 2 r 3 i
r 3 i 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 4 N 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
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
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.
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.
4 0 mult f4 – 0 0 0
1 ld f5 – 0 1 1
2 add f2 – 0 0 1
3 add f3 – 0 0 1
4 sub f2 – 0 0 1
Tabla 21. Estado del ROB en el momento en el que se produce la excepción en el problema
25.