Examen: 2021_01_21:GISAM - myTeachingURJC/Arq-computadores-01 GitHub Wiki

Examen convocatoria ordinaria: 2021-01-21. GISAM

  • Tiempo: 2h
  • Tipo de examen: Remoto. Realizado a través de Aula Virtual
  • Objetivo:
    • Resolver el problema de examen de la convocatoria ordinadira de GISAM, con fecha 2021/Enero/21

Contenido

Enunciado

El examen se ha realizado a través de Aula virtual

Pregunta 1 (2.5 puntos): Rendimiento

Se tienen dos implementaciones, 1 y 2, del mismo juego de instrucciones. El repertorio tiene cuatro clases de instrucciones: de tipo A, de tipo B, de tipo C y de tipo D. La frecuencia de reloj y el CPI de cada implementación se muestran en la siguiente tabla:

Fr CPI A CPI B CPI C CPI D
1 4 GHz 1 1 3 3
2 2 GHz 1 2 2 2

Para comparar ambas arquitecturas se utiliza un programa de pruebas en un lenguaje de alto nivel, que al compilarlo genera un total de 500 instrucciones, repartidas de la siguiente forma:

10% clase A
30% clase B
40% clase C
20% clase D

Responde a las siguientes preguntas:

  • a) Calcula el número de ciclos de reloj total que tarda cada arquitectura en ejecutar el programa de pruebas (0.5)
  • b) Calcula el CPI de cada arquitectura (0.5)
  • c) Calcula el tiempo de CPU total que tarda cada carquitectura en ejecutar el programa de pruebas (0.5)
  • d) A partir de los datos obtenidos en los apartados anteriores, indica qué arquitectura es la más rápida, y cuánto más rápida es una sobre la otra (0.5)
  • e) Si el mismo programa de prueba se implementa en otro lenguaje de alto nivel diferente del original, y se usa un compilador también distinto, justifica si los tiempos de CPU serían exactamente los mismos o habría cambios (0.5)

Pregunta 2 (2.5 Puntos): Repertorio de instrucciones

Un computador tiene una arquitectura registro-memoria, con 16 registros de propósito general de 32 bits, denotados por x0 - x15. Las direcciones de memoria son de 32 bits y las variables almacenadas en memoria son palabras de 32 bits también. El fabricante nos proporciona el formato de las instrucciones store, add (suma) y sub (resta)

La operación de suma realiza la operación: Reg = Reg + dato, y la de resta Reg = Reg - dato. El ensamblador acepta esta sintáxis para las instrucciones:

  • add reg, dir
  • sub reg, dir
  • store reg, dir

En memoria están almacenadas las variables a, b, y c. Se quiere hacer la operación g = a - b - c , dejando el resultado en la variable de memoria g. Supón que los registros del computador están inicialmente a 0

  • a) Escribe un fragmento de programa en el ensamblador de este computador que realice esta operación (0.5)
  • b) Calcula el número de accesos totales a memoria que se realizan, indicando cuáles son de lectura y cuáles de escritura (0.5)
  • c) Calcula el tráfico total en bytes que se intercambian el procesador y la memoria principal (1)
  • d) Supón que las variables a,b,c y g están situadas consecutivamente en la memoria, a partir de la dirección 0x2C008400, escribe el código máquina del programa del apartado a (0.5)

Pregunta 3 (2.5 Puntos): Circuitos lógicos

Dado el siguiente circuito

  • a) Explica brevemente la estructura y componentes de este circuito (0.5)
  • b) Calcula el *retardo+ de la parte combinacional (0.5)
  • c) Calcula la frecuencia máxima de funcionamiento a la que podría funcionar (0.5)
  • d) Si inicialmente todas las señales están a 0, indica el valor del registro transcurridos 3 ciclos de reloj. La señal Sel está todo el tiempo a 0 (0.5)
  • e) ¿Qué ocurre cuando Sel se pone a 1 durante varios ciclos de reloj? (0.5)

Pregunta 4 (2.5 Puntos): NanoRisc-V

Se ha construido el procesador NanoRISC-V monociclo cuyo esquema se muestra en la figura. El ingeniero Hardware nos ha proporcionado los siguientes datos sobre los componentes usados:

Componente Retardo
Memoria de instrucciones 170ps
Sumador 20ps
ALU 50ps
Memoria de datos 200ps
Banco de registros 80ps
Unidad de control 33ps

Para el resto de componentes supondremos que su retardo es despreciable por lo que asumiremos un valor de 0

  • a) Calcular el retardo de cada una de las fases: Fetch, Decodificación, Ejecución, Acceso a memoria y WriteBack para las instrucciones addi, ld, sd y beq (1 pto)
Instrucción Fetch Decod Ejecución Memoria WriteBack
addi
ld
sd
beq
  • b) Indicar cuál es la instrucción crítica y calcular la frecuencia máxima de funcionamiento (0.5)

  • c) El ingeniero hardware nos ofrece la posibilidad de incluir una unidad de control muchísimo más rápida que la actual, con un retardo de sólo 5ps. ¿Cuánto se mejora el rendimiento del procesador? (0.5)

  • d) Calcular la frecuencia máxima de funcionamiento si ahora utilizamos la versión Multiciclo del NanoRISC-V, con los mismos datos de la tabla inicial, y suponiendo que el resto de componentes tienen un retardo igual a 0 (0.5)

Figura del Risc-V Monociclo

Figura del Risc-V Multiciclo

Solución comentada

En estas soluciones se ha puesto lo que se supone que un estudiante con conocimientos suficientes debería escribir para tener la respuesta correcta: el resultado y la justificación de ese resultado. Además, se han incluido comentarios adicionales, que no serían parte de la solución, para aclarar conceptos y ayudar en la asimilación del conocimiento cuando se estén preparando los exámenes. También se incluyen algunos de los razonamientos y decisiones que tiene que tomar el estudiante y que deben ocurrir en su cabeza

Pregunta 1: Rendimiento

COMENTARIOS: Antes de responder, tienes que entender el contexto del enunciado. Pensar sobre él, para aclarar todas las dudas. Porque, aunque uno haya estudiado mucho, SIEMPRE tendrá dudas. Tienes que aprender a resolverte estas dudas y a aclararte las ideas, para poder así dar una respuesta coherente y con seguridad. Una gran parte de la resolución del examen es justamente esto

COMENTARIOS: El programa de pruebas que se está usando es el mismo para las dos implementaciones, lógicamente. Si se usasen programas diferentes, no se podrían hacer comparaciones en las mismas condiciones. Como las dos implementaciones tienen el mismo juego de instrucciones, las dos pueden ejecutar sin problemas el código máquina obtenido a través del compilador. Es decir, que el ejecutable es el mismo para ambos computadores

  • a) Calcula el número de ciclos de reloj total que tarda cada arquitectura en ejecutar el programa de pruebas (0.5)

    Para calcular el número de ciclos que tarda cada arquitectura tendremos que sumar el número de ciclos que tarda cada una de las instrucciones que se ejecutan. En cada arquitectura las instrucciones tardan un número distinto de ciclos. Esto lo hacemos multiplicando el Número de instrucciones de cada tipo por su CPI y los sumamos. I es el número total de instrucciones del programa de prueba: 500

    • Arquitectura 1: (I * 0.1 * 1) + (I * 0.3 * 1) + (I * 0.4 * 3) + (I * 0.2 * 3) = 1100 ciclos

    COMENTARIOS: Cada término entre paréntesis se corresponde con el número de instrucciones de cada tipo. El primero son los ciclos que tardan las instrucciones de tipo A, el segundo las de tipo B, luego las de tipo C y finalmente las de tipo C. El número de instruccion de un tipo se obtiene multiplicando I por su porcentaje

    • Arquitectura 2: (I * 0.1 * 1) + (I * 0.3 * 2) + (I * 0.4 * 2) + (I * 0.2 * 2) = 950 ciclos

    COMENTARIOS: Aunque no se pide en este apartado, tras obtener unos resultados siempre hay que pararse a reflexionar sobre ellos, para ver si tienen sentido o no, y entender bien lo que se ha obtenido. La arquitectura 1 tiene que emplear más ciclos de reloj que la arquitectura 2, por lo que, a priori, parece que es más lenta. Sin embargo, para determinar si una arquitectura es mejor que otra, no se usa este criterio aislado. Hay que tener en cuenta no sólo el número de ciclos de reloj, sino también la frecuencia de funcionamiento

  • b) Calcula el CPI de cada arquitectura (0.5)

    COMENTARIOS: Cada instrucción tarda un número de ciclos diferente, que en el enunciado me lo han dado en forma de tabla. Sin embargo, cuando hablamos de CPI de una arquitectura nos referimos a su valor medio. El número de ciclos, que en media, tiene las instrucciones.

El CPI lo calculamos dividiendo el número de ciclos totales empleados en la ejecución del programa de prueba, dividido entre el número total de instrucciones que tiene

  • Arquitectura 1: CPI1 = ciclos1 / I = 1100 / 500 = 2.2
  • Arquitectura 2: CPI2 = ciclos2 / I = 950 / 500 = 1.9

COMENTARIOS: Una vez más, la arquitectura 1 parace más lenta, ya que sus instrucciones, en media, requieren de más ciclos de reloj que en la arquitectura 2. Los valores obtenidos, ademas, son coherentes. Si hubiésemos obtenido un valor menor que uno, sería incorrecto. No puede ocurrir, así que tendríamos que revisar los cálculos. Si nos saliese 1 lo mismo. El CPI sólo puede ser 1 si todas y cada una de sus instrucciones se ejecuta en un ciclo de reloj.

  • c) Calcula el tiempo de CPU total que tarda cada carquitectura en ejecutar el programa de pruebas (0.5)

COMENTARIOS: Lo que nos están pidiendo es: "¿Cuanto tiempo tarda cada computador en ejecutar el programa de pruebas?". Y este es el criterio DEFINITIVO para saber cuál de los dos es mejor: el que tarde menos tiempo. Al final, el tiempo es lo más imporatante: si un computador ejecuta el mismo programa en menos tiempo, será mejor

El tiempo de CPU se calcula multiplicando el número de ciclos totales por el periodo de cada ciclo, que es la inversa de la frecuencia

  • Arquitectura 1: Tcpu1 = Ciclos1 * T1 = 1100 * 1 / Frec = 1100 * 1 / 4GHz = 1100 / 4 ns = 275 ns

  • Arquitectura 2: tcpu2 = ciclos2 * T2 = 950 * 1 / Frec = 950 * 1 / 2GHz = 950 / 2 = 475 ns

COMENTARIOS: Ahora aquí ya sí vemos la realidad: que el computador 1 es mejor que el computador 2, porque tarde menos tiempo en ejecutar el mismo programa. Y justamente esto es lo que nos piden en el apartado anterior, pero mediante este tiempo que hemos dedicado a reflexionar, nos hemos anticipado

  • d) A partir de los datos obtenidos en los apartados anteriores, indica qué arquitectura es la más rápida, y cuánto más rápida es una sobre la otra (0.5)

Para comparar arquitecturas usamos el rendimiento relativo:

n = Rend1 / Rend2 = Tcpu2 / Tcpu1 = 475 / 275 = 1.73

La arquitectura 1 es 1.73 veces más rápida que la 2

  • e) Si el mismo programa de prueba se implementa en otro lenguaje de alto nivel diferente del original, y se usa un compilador también distinto, justifica si los tiempos de CPU serían exactamente los mismos o habría cambios (0.5)

Tanto el lenguaje empleado como el compilador determinarán qué tipo de instrucciones se usan y cuántas hay en el programa de prueba. Al utilizar otro lenguaje y otro compilador, el número de instrucciones usado de cada tipo variará y por tanto los tiempos de cpu también variarán (Por ejemplo, el compilador podría generar más instrucciones de tipo D que tipo A)

COMENTARIOS: Es precisamente por esto, que al evaluar el rendimiento de un computador, no sólo es importante la frecuencia a la que funcione, sino que hay más factores a tener en cuenta: el lenguaje empleado, el compilador, el programa de prueba... Esto es importante para que, como ingenieros, seamos nosotros los que tomemos la decisión correcta y sepamos analizar con criterio los datos proporcionados por un fabricante. El fabricante te dará siempre los mejores datos. Seleccionará los programas de pruebas y compiladores en los que su procesador salga ganando frente a la competencia. Pero, podría ser que al cambiar el compilador, por ejemplo, el rendimiento empeorase

Pregunta 2: Repertorio de instrucciones

COMENTARIOS: Como siempre, hay que leer el enunciado detenidamente, y dedicar unos minutos a pensar sobre él, antes de empezar a contestar las preguntas. Como este computador tiene una arquitectura registro-memoria, dispondrá de instrucciones en las que alguno de los operandos se encuentren en memoria. Y efectivamente, viendo las instrucciones add, sub y store que nos definen, el segundo operando en todas ellas hace referencia a memoria

  • a) Escribe un fragmento de programa en el ensamblador de este computador que realice esta operación (0.5)

COMENTARIOS: En la parte de teoría vemos en general el funcionamiento de los computadores, por lo que los programas que hacemos son bocetos, o esquemas, sin entrar en demasiados detalles (los detalles los vemos en la parte de laboratorio, para el procesador RISC-V). Por eso, en estos programas que nos piden no usamos directivas ni definimos etiquetas. Nos centramos en dar la idea general.

COMENTARIOS: Para implementar la operación g = a - b - c con las instrucciones disponibles se puede hacer de múltiples maneras. En todo lo referente a la programación, la solución nunca es única. Una solución sencilla es implementarlo de forma directa: primero asignamos hacemos g = a, y luego le restamos b y c. En el repertorio disponible NO tenemos una instrucción de asignación. Lo único que tenemos es la instrucción de add. Como nos dice el enunciado que supongamos que todos los registros están incialmente a 0, la instrucción add tendrá juso este efecto: reg = 0 + a

COMENTARIOS: Para implementar los cálculos intermedios necesitamos usar un registro. Como no nos dan restricciones, podemos usar el registro que queramos, como por ejemplo el x1 (pero sería válido cualquier otro, incluso el x0, porque no me están diciendo que en esta arquitectura el registro x0 sea 0, como ocurre en los RISC-V)

add x1, a   #-- x1 = 0 + a, porque x1 inicialmente vale 0
sub x1, b   #-- x1 = x1 - b
sub x1, c   #-- x1 = x1 - c
store x1, g #-- Almacenar x1 en g
  • b) Calcula el número de accesos totales a memoria que se realizan, indicando cuáles son de lectura y cuáles de escritura (0.5)

COMENTARIOS: Cuando hablamos de accesos a memoria nos referimos a las veces que hay que acudir a la memoria para obtener una variable o una instrucción. Según la memoria física utilizada en la implementación, para leer una palabra de 32 bits necesitaríamos más o menos accesos. Pero como no nos indican nada, estamos suponiendo que la memoria tiene la misma anchura que los datos o instrucciones que usa. Así que para nosotros habrá un acceso cada vez que se lee una instrucción, y un acceso para cada lectura o escritura de variable

Las instrucciones están en memoria, por lo que para ejecutar cada una de ellas hay que leerla primero de memoria. Por tanto habrá 4 accesos de lectura para leer las instrucciones.

Al ejecutar las instrucciones add y sub, hay un acceso a memoria, para leer la variable indicada. En la instrucción store hay 1 acceso de escritura

  • Número de accesos de lectura = 4 + 3 = 7
  • Número de accesos de escritura = 1
  • Total número de accesos a memoria: 8

COMENTARIOS: Este resultado es coherente. Si nos saliese por ejemplo un valor de 3, que es menor al número de instrucciones, sabríamos que habría algún error en algún sitio: para ejecutar el programa al menos debe haber 4 accesos a memoria para leer las instrucciones

  • c) Calcula el tráfico total en bytes que se intercambian el procesador y la memoria principal (1)

A partir del formato de las instrucciones, vemos que tienen un tamaño de 40 bits (5 bytes). El tráfico generado para la lectura de las instrucciones es de 4 * 5 = 20 bytes. Las variables de memoria son de 32 bits (4 bytes). En todas las instrucciones se lee o escribe una variable, por lo que se transfieren 4 * 4 = 16 bytes

Por tanto, el tráfico total es de: 20 + 16 = 36 bytes

  • d) Supón que las variables a,b,c y g están situadas consecutivamente en la memoria, a partir de la dirección 0x2C008400, escribe el código máquina del programa del apartado a (0.5)

COMENTARIOS: Pensamo primero en cómo están situadas las variables en la memoria. Sabemos que son variables de 32 bits, por lo que ocuparán 4 bytes. Las memorias se direccionan por bytes, por lo que si la primera variable está en la dirección 0x2C008400, las siguientes estarán 4 bytes más arriba cada una de ellas: 0x2C008404 (b), 0x2C008408 (c) y 0x2C00840C (g)

Cada instrucción consta de su código de operación, el número del registro que usa y la dirección a la que accede (la variable). En todas las instrucciones se usa el registro x1, que se codifica en 4 bits como 0001. Si lo ponemos en hexadecimal sería: 0x1

En esta table se muestran las instrucciones descompuestas en sus diferentes campos:

Instruccion Direccion Registro Opcode Código máquina
add x1, a 0x2C008400 0x1 0xA 0x2C0084001A
sub x1, b 0x2C008404 0x1 0xB 0x2C0084041B
sub x1, c 0x2C008408 0x1 0xB 0x2C0084081B
store x1, b 0x2C00840C 0x1 0xF 0x2C00840C1F

El programa en código máquina es, por tanto:

0x2C0084001A
0x2C0084041B
0x2C0084081B
0x2C00840C1F

COMENTARIOS: Durante el examen un estudiante preguntó si el código máquina había que ponerlo en binario o en hexadecimal. En el enunciado no se dice explícitamente cómo ponerlo. Por ello aplicamos el sentido común del ingeniero: si no está especificado utilizamos lo que resulte más sencillo. En este caso es el hexadecimal. Si lo hacemos en binario se convierte en un pequeño infierno: hay que escribir 128 bits. La probabilidad de error es altísima

COMENTARIOS: Gran parte del tiempo de las clases síncronas de teoría (bien presenciales o bien online) las dedico precisamente a esto: a aprender a desarrollar el sentido común del ingeniero. En la vida real los problemas están vagamente especificados, o se dan por supuestas muchas cosas. Es clave para el ingeniero desarrollar este sentido común (que por otro lado sólo se obtiene si se practica)

Pregunta 3: Circuitos lógicos

COMENTARIOS: Como siempre, primero dedicamos un tiempo a pensar sobre el circuito que nos dan. Tiene un registro (su parte secuencial) y dos circuitos combinacionales: un sumador y un multiplexor. Aunque en el dibujo la parte combinacional está separada: el multiplexor a la izquierda del registro y el sumador a su derecha, en realidad quedan unidas por la etiqueta Next. Por tanto, es el típico circuito con una parte combinacional y una secuencial, que están realimentadas. Este sería un esquema equivalente que representa el mismo circuito:

  • a) Explica brevemente la estructura y componentes de este circuito (0.5)

El circuito está formado por la conexión en anillo de un registro de 8 bits (parte secuencial) con otro circuito combinacional, que a su vez está dividido en un sumador de 8 bits y un multiplexor (ambos combinacionales)

  • b) Calcula el retardo de la parte combinacional (0.5)

El retardo de la parte combinacional lo determina el camino que va desde la salida del registro hasta llegar otra vez a su entrada: 2ns (sumador) + 2n (mux) = 4ns

  • c) Calcula la frecuencia máxima de funcionamiento a la que podría funcionar (0.5)

Para el cálculo de la frecuencia máxima tenemos que calcular el tiempo mínimo que transcurre desde que hay un dato estable en la entrada del registro hasta que llega un nuevo dato estable. Este tiempo es de: 4ns + 4ns = 8ns. Por tanto, la frecuencia máxima de funcionamiento es de: 1 / 8ns = 125Mhz

  • d) Si inicialmente todas las señales están a 0, indica el valor del registro transcurridos 3 ciclos de reloj. La señal Sel está todo el tiempo a 0 (0.5)

Como la señal sel está a 0, lo que llega a la entrada del registro es su propio valor incrementado en una unidad (configuración típica en anillo). Por tanto, en el primer ciclo se captura un 1, en el segundo un 2 y en el tercero habrá un 3

  • e) ¿Qué ocurre cuando Sel se pone a 1 durante varios ciclos de reloj? (0.5)

    Cuando sel se pone a 1, lo que llega a la entrada del registro es un 0, por lo que el registro se inicializa. Mientras sel valga 1, el registro valdrá 0

Pregunta 4: NanoRisc-V

COMENTARIOS: Se nos proporciona el esquema del NanoRisc-V Monociclo, que hemos usado en las clases. Lo primero es analizar el esquema y comprobar si hay alguna variación con respecto a lo que hemos usado normalmente. Las preguntas se responden justificándolo según este esquema

  • a) Calcular el retardo de cada una de las fases: Fetch, Decodificación, Ejecución, Acceso a memoria y WriteBack para las instrucciones addi, ld, sd y beq (1 pto)

Dado que todos los componetes tiene un retardo 0 salvo los indicados en las tablas, los retardos de fase serán:

  • Fetch: Determinado únicamente por la memoria de instrucciones
  • Decod: Determinado únicamente por el banco de registros
  • Ejecución: Determinado por la ALU
  • Memoria: Determinado por la memoria de datos
  • WriteBack: Será siempre 0 salvo para beq, que está determinado por el retardo del sumador

En este ejercicio nos están dando el retardo de la unidad de control. La generación de las señales de control se hace en paralelo con la fase de decodificación en la ruta de datos, que lleva más tiempo. Por tanto, el camino crítico es debido al retardo del banco de registros

Instrucción Fetch Decod Ejecución Memoria WriteBack Total
addi 170ps 80ps 50ps 0 0 300ps
ld 170ps 80ps 50ps 200ps 0 500ps
sd 170ps 80ps 50ps 0 0 300ps
beq 170ps 80ps 50ps 0 20 320ps
  • b) Indicar cuál es la instrucción crítica y calcular la frecuencia máxima de funcionamiento (0.5)

La instrucción crítica es la que tarda más tiempo en ejecutarse. Es la de load, con un retardo de 500ps. Por tanto, será la instrucción que determina la frecuencia máxima de funcionamiento del procesador: 1 / 500ps = 2Ghz

  • c) El ingeniero hardware nos ofrece la posibilidad de incluir una unidad de control muchísimo más rápida que la actual, con un retardo de sólo 5ps. ¿Cuánto se mejora el rendimiento del procesador? (0.5)

Por lo indicado en el apartado a, el retardo de la unidad de control es menor que el del banco de registros, por lo que su valor no determina el de la etapa de decodificación. Aunque se reduzca este tiempo, la frecuencia de funcionamiento seguirá siendo la misma: 2GHz

  • d) Calcular la frecuencia máxima de funcionamiento si ahora utilizamos la versión Multiciclo del NanoRISC-V, con los mismos datos de la tabla inicial, y suponiendo que el resto de componentes tienen un retardo igual a 0 (0.5)

Para calcular la frecuencia del multiciclo nos tenemos que fijarnos en la etapa más lenta, que es la de acceso a la memoria de datos: 200ps. Por tanto, la frecuencia será: 1 / 200ps = 5Ghz

Autores

Licencia

Enlaces