El
siguiente programa (pract2v1.s)
se encarga de multiplicar todos los números de la lista almacenada
por el número pi,
dejando los resultados almacenados en las mismas posiciones.
.data
0
a:
.double 3.14159265358979
x:
.double 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16
.double
17,18,19,20,21,22,23
xtop:
.double 24
.text
256
start:
ld f2,a (1)
addi
r1,r0,xtop (2)
loop:
ld f0,0(r1) (3)
multd
f4,f0,f2 (4)
sd
0(r1),f4 (5)
subi
r1,r1,8 (6)
bnez r1,loop
(7)
trap
6 (8)
|
Práctica
2.- pract2v1.s
Considerar
inicialmente las siguientes opciones de configuración:
-
Unidad de suma: latencia 2 ciclos
-
Unidad de multiplicación: latencia 5 ciclos
-
Unidad de división: latencia 19 ciclos
-
Unidades funcionales sin segmentar
-
Saltos: predicción de no tomar
-
Adelantamiento de resultados: desactivado
Luego
B, adelanto de resultados activados es un 33% más rápida que A,
adelanto de resultados desactivados.
b)
Partiendo de la configuración inicial, considere que se efectúa una
mejora en la unidad de multiplicación, reduciendo su retardo a 3
ciclos. Esta mejora supone un incremento del coste del 15%. Determine
si, para este programa, compensa realizar dicha mejora desde el punto
de vista de la relación coste/prestaciones.
Para
hacer este ejercicio debemos modificar la configuración inicial de
la latencia de multiplicación: Configuración
-> Arquitectura
he introducimos 2 para que salga el resultado esperado 3.Ejecutamos
el programa. Nos volvemos a fijar en la ventana de Estadísticas
-> Ciclos
c)
Considere que la mejora consiste en reducir el retardo de la unidad
de multiplicación a 2 ciclos, con un incremento del coste del 18%.
¿Compensa la mejora?
Para
hacer este ejercicio debemos modificar la configuración inicial de
la latencia de multiplicación: Configuración
-> Arquitectura
he introducimos 1 para que salga el resultado esperado 2.Ejecutamos
el programa. Nos volvemos a fijar en la ventana de Estadísticas
-> Ciclos
Luego,
al mejorarlo se consigue mejorar un 23% y al ser los costes un 18%,
nos interesa mejorar porque los costes superan las prestaciones.
d)
¿Tendría interés mejorar la latencia de la unidad suma?
Probablemente
no tendrá interés, ya que, aunque se hace una instrucción
addi,sólo se hace en un único ciclo y probablemente el coste de la
reducción sea elevado.
En el salto retardado se reordena el código de forma que se sitúan instrucciones que no dependan del salto después del mismo para que se vayan ejecutando esas instrucciones (que siempre se van a ejecutar) y cuando se termine de calcular el salto se toma o no. Pero en este programa hay un problema. Lo que pasa es que antes de que se decida el salto, como se siguien ejecutando instrucciones, SE EJECUTA LA TRAP DE SALIDA ANTES DE QUE SE TOME EL SALTO. Por eso solo hace una iteración del bucle y finaliza, con lo cual no se ejecuta bien el programa. La solución sería poner más instrucciones independientes a ejecutarse después del salto, para que no se ejecute el trap antes de coger el salto.
Determinar
la ganancia de velocidad que se obtiene con respecto a la versión
inicial del programa.
.data
0
a:
.double 3.14159265358979
x:
.double 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16
.double
17,18,19,20,21,22,23
xtop:
.double 24
.text
256
start:
ld f2,a (1)
addi
r1,r0,xtop (2)
loop:
ld f0,0(r1) (3)
multd
f4,f0,f2 (4)
sd
0(r1),f4 (5)
ld
f6,-8(r1) (6)
multd
f8,f6,f2 (7)
sd
-8(r1),f8 (8)
ld
f10,-16(r1) (9)
multd
f12,f10,f2 (10)
sd
-16(r1),f12 (11)
ld
f14,-24(r1) (12)
multd
f16,f14,f2 (13)
sd
-24(r1),f16 (14)
subi r1,r1,32
(15)
bnez r1,loop
(16)
trap 6
(17)
|
Práctica
2.- pract2v2.s
Para
empezar a hacer el ejercicio cargamos el programa Herramientas
-> Editar
y para introducir las opciones de configuración iniciales
Configuración
-> Arquitectura
he introducimos los datos de latencia (para que salgan los resultados
que esperamos 2, 5, 19; debemos poner 1, 4, 18) y desactivamos el
segmentado; saltos: Configuración
-> Saltos -> Predicción de no tomar,
y finalmente, Configuración
-> Adelanto de resultados.
Para simular el programa le damos a la flechita verde.
Luego
B, aplicando la técnica desenrollado
de bucle
es un 30% más rápida que A, sin aplicar dicha técnica.
En
el proceso DLXssr cada instrucción va pasando por distintas fases
que se suceden según sean utilizadas por la correspondiente
instrucción, de forma que las instrucciones tendrán distinto tiempo
de ejecución según del tipo que sean.
Consideramos
que en DLXssr las fases
IF, ID, intEX, MEM y
WB
tienen un ciclo de reloj cada una. Las fases faddEX,
fmultEX
y fdivEX
tendrán
el mismo número de ciclos que en el caso del procesador segmentado.
Para
estimar el tiempo de ejecución del programa en DLXssr hay que tener
en cuenta el tiempo que tardaría cada una de sus instrucciones. El
tiempo de instrucción se puede determinar a partir del número de
etapas por las que pasa. Así, por ejemplo, una instrucción de carga
(Id)
pasaría por todas las etapas (duración 5 ciclos de reloj) mientras
que una instrucción de almacenamiento (sd)
no pasaría por WB (duración 4 ciclos de reloj) ya que no tiene que
almacenar nada en los registros del procesador. Las instrucciones
aritmético-lógicas no pasarían por la etapa de MEM. Hay que tener
en cuenta que la duración de la etapa EX depende del tipo de
instrucción: si la operación es con enteros, se utilizará intEX
y la duración será de un ciclo; si es en coma flotante, se
utilizará faddEX,
fmulEX o fdivEX
y en la duración será la asignada a la correspondiente unidad.
Para
las instrucciones de salto condicional considere una duración de 3
ciclos (en la etapa de ejecución se comprueba la condición y se
carga en el PC la nueva dirección, si fuese el caso). Para el trap
considere 2 ciclos (hasta la etapa de codificación).
Tenemos
24 elementos en el vector. A cada uno de ellos lo sacamos del vector
y lo multiplicamos por PI.
Entonces por cada elemento hacemos un
ld
(cargar
en registro)
multd (multiplicar)
y sd
(volver
a guardarlo en el mismo sitio). Luego 3 instrucciones por elemento
3*24 = 72
instrucciones.
Además,
se hacen más instrucciones. En cada iteración del bucle se hace una
resta
y la comparación
del salto.
En esta versión del programa se hacen 4 multiplicaciones por bucle,
luego 24/4 =
6 iteraciones,
es decir
6*2
= 12 instrucciones.
Se
ejecutan al principio otras dos instrucciones una
carga
y una
suma.
En trap
contamos dos
ciclos.
Entonces, 72+12+2+trap
= 87 instrucciones.
Como
el DLXssr no es segmentado cada instrucción dura tantos ciclos como
tenga (LW dura 5 ciclos, pero sw y add duran solo 4 ciclos, mientras
que el salto dura 3 ciclos y la trap 2), solo hay que saber contar
cuántas hay de cada una.
LD
(load double) → 24 instrucciones * 5 ciclos = 120
ciclos;
MultD → Tienen 4
ciclos pero hay que contar la latencia de mult, que es 5 ciclos,
luego son 3(IF,ID, WB) + 5 de ejecutar la operación = 8 ciclos
/instrucción * 24 instrucciones = 192
ciclos.
SD
(store double) → 24 instrucciones * 4 ciclos = 96
ciclos.
Subi
(substract inmediate) → se hacen 6 instrucciones que duran 4 ciclos
(son restas de enteros), luego 6*4=24
ciclos.
Beqz
(El salto) 6 instrucciones * 3 ciclos = 18
ciclos.
De
las dos instrucciones del principio, la carga es de 5 ciclos, y la
suma de 4, luego 9
ciclos.
trap
vale 2
ciclos.
Sumando
en total salen 120+192+96+24+18+9+2=461 ciclos.
A:
Ejercicio 1-> 408 ciclos
B:
Ejercicio 4: 461 ciclos
Luego
B, ejercicio 4, no segmentado, es un 33% más lenta que A, ejercicio
1, segmentado.
Nos
fijamos en la ventana Estadísticas
los ciclos, después activamos el adelanto de resultados
Configuración
-> Adelanto de resultados,
simulamos de nuevo el programa y nos volvemos a fijar en los ciclos.
Luego
B, ejercicio 5 es un 9% más rápida que A, ejercicio 3.
El
programa modificado que planteamos es:
Cargamos
el programa Herramientas
-> Editar
y para introducir las opciones de configuración iniciales
Configuración
-> Arquitectura
he introducimos los datos de latencia (para que salgan los resultados
que esperamos 2, 5, 19; debemos poner 1, 4, 18) y desactivamos el
segmentado; saltos: Configuración
-> Saltos -> Predicción de no tomar,
y finalmente, Configuración
-> Adelanto de resultados.
Para simular el programa le damos ala flechita verde.
Nos
fijamos en la ventana Estadísticas
los ciclos, después activamos el adelanto de resultados
Configuración
-> Adelanto de resultados,
simulamos de nuevo el programa y nos volvemos a fijar en los ciclos.
Luego
B, ejercicio 6 es un 56% más rápida que A, ejercicio 3.