P3: Caché en la Pico - myTeachingURJC/Arq-computadores-01 GitHub Wiki

Sesión 3: Memoria caché

En esta práctica pondremos en práctica los conceptos estudiados de memoria caché.

IMPORTANTE: Para realizar esta práctica, es necesario que hayas leído en casa antes la sesión S4 hasta caché de varios niveles (no incluido), ábrela en otra pestaña para consultar conceptos que no recuerdes.

Solo necesitaremos la RPi y el cable USB, guarda el resto de elementos dentro de la caja.

1. Efecto de la memoria caché en la lectura de instrucciones

Como hemos visto en la S4, la memoria caché hace que la lectura de la memoria sea más rápida.

Vamos a utilizar un programa de prueba, en el que medimos únicamente el número de ciclos que tarda en ejecutarse una instrucción addi:

.include "compile/gpio.s"

.global asm_main   #-- Punto de entrada


.eqv MTIME_CTRL,   0xD00001A4  #-- Timer Control 
.eqv MTIME,        0xD00001B0  #-- Temporizador del RISCV

.eqv GPIO_BASE,       0xD0000001
.eqv GPIO_IN_OFFSET,  0x5
.eqv GPIO_OUT_OFFSET, 0x10

.data
msg: .string "\n\n N ciclos: "

.text

# -- Punto de entrada
asm_main:

    #-- Inicializar GPIOs
    jal init

    #-- Arrancar temporizador
    li t0, MTIME_CTRL
    li t1, 0x3
    sw t1, 0(t0)

loop:

    li s1, 0

#-- Comenzar medición
    li t5, MTIME
    lw s4, 0(t5)

    #-- Código a medir
    addi s1, s1, 1

#-- Terminar la medición
    lw s5, 0(t5)
    sub s4, s5, s4
    addi s4, s4, -1

#-- Imprimir resultado
    la a0, msg
    jal print
    mv a0, s4
    jal print_unsigned_int

#-- Espera de medio segundo
    li a0, 500
    jal sleep_ms

#-- Bucle infinito
    j loop

Copia y pega este código en un archivo que se llame p3_a.s, ensámblalo y cárgalo en la RPi

Abre el monitor serie para ver lo que imprime la RPi. Recuerda activar la opción de reconexión automática.

Para ver los ciclos que se imprimen desde el principio, sin cerrar el monitor, desconecta y conecta el usb de la RPi.

Observa los ciclos que indica que tarda en ejecutar addi.

Pregunta 1: ¿Hay alguna diferencia entre los ciclos en la primera ejecución y las siguientes?¿A qué puede deberse?

2. Caché en la lectura de datos

Ahora vamos a medir cuánto tarda en ejecutarse una instrucción que accede a memoria, en concreto lw.

Utilizaremos este código en el que se leen todos los números de un array de 20 números y se mide el número de ciclos que se tarda en leer el dato con lw.

El programa imprime el número leído, y después el número de ciclos que ha tardado. Después de leer los 20 números, termina.

.include "compile/gpio.s"

.global asm_main   #-- Punto de entrada


.eqv MTIME_CTRL,   0xD00001A4  #-- Timer Control 
.eqv MTIME,        0xD00001B0  #-- Temporizador del RISCV

.eqv GPIO_BASE,       0xD0000001
.eqv GPIO_IN_OFFSET,  0x5
.eqv GPIO_OUT_OFFSET, 0x10

.section .rodata
cad:
    .word 1, 2, 3, 4, 5, 6, 7, 8, 9, 10
    .word 11, 12, 13, 14, 15, 16, 17, 18, 19, 20

.data
msg: .string "\n N ciclos: "
msg2: .string "\n\n Numero: "

.text

# -- Punto de entrada
asm_main:

    #-- Inicializar GPIOs
    jal init

    #-- Arrancar temporizador
    li t0, MTIME_CTRL
    li t1, 0x3
    sw t1, 0(t0)

    la s0, cad

loop:


#-- Comenzar medición
    li t5, MTIME
    lw s4, 0(t5)

    #-- Código a medir
    lw s1, 0(s0)

#-- Terminar la medición
    lw s5, 0(t5)
    sub s4, s5, s4
    addi s4, s4, -1

#-- Imprimir el número
    la a0, msg2
    jal print
    mv a0, s1
    jal print_unsigned_int

#-- Imprimir el número de ciclos
    la a0, msg
    jal print
    mv a0, s4
    jal print_unsigned_int

    #-- Espera de medio segundo
    li a0, 500
    jal sleep_ms

    #-- Incremento de puntero
    addi s0, s0, 4

    #-- Si no hemos llegado al final repetimos
    li t2, 76
    blt s0, t2, loop

fin:
    j fin

Copia el código en el archivo p3_b.s, ensámblalo y pruébalo.

¿Observas alguna diferencia en el número de ciclos que se tarda en leer cada número?¿A qué se debe?

Pregunta 2: Indica cuánto tarda en leer los datos que tiene en caché (aciertos), y cuánto los que no tiene en caché (fallos). Para simplificar asume que todo el tiempo de ciclo se consume en leer de memoria y que la frecuencia del procesador es de 150MHz

Pregunta 3: obtén para esas 20 lecturas de memoria, la tasa de aciertos, la tasa de fallos y el tiempo medio de lectura.

Pregunta 4: Determinar el tamaño del bloque de caché basado en lo que observas (en bytes)

3. Aprovechando la caché

En el ejemplo anterior, a pesar de que cada dato que leíamos era nuevo, al guardarse en caché por bloques, vemos cómo se mejora el rendimiento y en muchos ciclos se leía el dato de caché reduciendo el tiempo medi de lectura.

Ahora, vamos a ver cómo se comporta la caché si ya ha leído alguna vez los datos de memoria. Para ello, modifica el código anterior, y haz que, cuando llegue al número 20, en lugar de terminar en un bucle infinito, se resetee el puntero y se vuelvan a leer otra vez. El programa debe leer en bucle los 20 números de memoria.

Observa cuánto tarda en leer de memoria los datos a partir de la segunda iteración del bucle (la segunda vez que lee el array)

Pregunta 5: ¿Cuál es la tasa de fallos y el tiempo medio de lectura a partir de la segunda iteración?

4. Clase teórica caché, políticas de reemplazo, etc.

Explicación o lectura del resto de la sesión S4, a partir de caché de varios niveles


Autores

Enlaces

Licencia