Está en la página 1de 8

6.

Memoria cache

6.3 Principio de localidad


La memoria caché es una memoria pequeña y rápida que se interpone entre la CPU y
la memoria principal para que el conjunto opere a mayor velocidad. Para ello es
necesario mantener en la caché aquellas zonas de la memoria principal con mayor
probabilidad de ser referenciadas. Esto es posible gracias a la propiedad de localidad
de referencia de los programas.
Es decir, los programas, durante su ejecución, no acceden con la misma probabilidad
a todos sus datos o instrucciones.
La localidad de referencia se manifiesta en una doble dimensión: temporal y espacial.

Localidad temporal: cuando un programa hace referencia a una locación de


memoria, muy probablemente vaya a acceder de nuevo a ella en el corto plazo. Esto
se produce debido a que los programa, en general, consumen mucho tiempo en
iteraciones o en actividades recursivas, por lo que recorren la misma sección de
código una enorme cantidad de veces.

Localidad espacial: se plantea que tras una referencia a una posición de memoria
dada, es mucho más probable que se acceda a posiciones cercanas a ella que a
posiciones lejanas a la misma. Esto deriva de la tendencia a almacenar los datos en
zonas contiguas.

Para entender mejor este concepto, veamos un ejemplo:


 Tras el acceso (ejecución) a la instrucción Ins_3, existe una elevada probabilidad de
que dicha instrucción vuelva a ser accedida pronto.
 Tras el acceso (de lectura o escritura) al dato Dat_3, existe una elevada probabilidad
de que dicho dato vuelva a ser accedido pronto.

6.4 Bloques en RAM y líneas en cache.

La memoria cache está directamente relacionada con la memoria principal ya que,


como mencionamos anteriormente, la primera se encuentra presente entre la memoria
principal y la unidad central de procesos, con el objeto de almacenar los contenidos de
las direcciones a las que se accede con mayor frecuencia.
La cache contiene una copia de partes de la memoria principal.
Durante la ejecución de un programa, se analiza primero el contenido de la memoria
cache, y se accede a la palabra requerida si estuviese presente en la misma (acierto
de cache). Si la palabra a la que se hace referencia no está presente en la memoria
cache (fallo de cache), se genera una posición vacía y se carga la palabra requerida
en esa posición desde la memoria principal, tras lo cual se accede en la memoria
cache a la palabra solicitada.
Si bien este proceso lleva más tiempo que el acceso directo a la memoria principal, el
rendimiento general mejora cuando se logra que una proporción alta de accesos a la
memoria se satisfaga desde la memoria cache.

La siguiente figura muestra la estructura de un sistema de memoria cache/principal.

La memoria principal consta de hasta 2𝑛 palabras direccionables, teniendo cada


palabra una única dirección de n bits. Esta memoria se encuentra dividida en un
numero de bloques de longitud fija, de K palabras por bloque. Entonces, hay M= 2𝑛 /K
bloques.
Por otro lado, la cache consta de C líneas. Cada línea contiene K palabras, más una
etiqueta de unos cuantos bits, denominándose tamaño de línea al número de palabras
que hay en la línea. El número de líneas es considerablemente menor que el número
de bloques de memoria principal. En todo momento, un subconjunto de los bloques de
memoria reside en líneas de la cache. Ya que hay más bloques que líneas, una línea
dada no puede dedicarse univoca y permanentemente a un bloque. Por consiguiente,
cada línea incluye una etiqueta que identifica que bloque particular almacena.

Por ejemplo, si tenemos una memoria caché de 32 bytes organizada en 8 bloques de


4 bytes y una memoria principal de 256 bytes, entonces:

2𝑛 bytes = 256 bytes = 28 palabras direccionables

n = 8 = cantidad de bits de cada palabra

4 es la cantidad de palabras por bloque


28
Entonces, 𝑀 = → 𝑀 = 64 bloques
4

Por lo tanto, la memoria principal tiene 64 bloques de 4 bytes cada uno.

6.5 Políticas de lectura y escritura


Toda memoria caché lleva asociado un controlador de memoria caché, el cual se
encarga de gestionar todas las lecturas y escrituras en la memoria caché y decidir por
ejemplo si una dirección está cacheada, es decir, ubicada dentro de la memoria caché,
o por el contrario se ha producido un fallo de caché, es decir, no está ubicada dentro
de la memoria cache.

Hay dos casos a considerar cuando se ha de reemplazar un bloque de la cache. Si el


bloque antiguo de la cache no debe ser modificado, puede sobrescribirse con el nuevo
bloque sin necesidad de actualizar el antiguo. Si se ha realizado al menos una
operación de escritura sobre una palabra de la línea correspondiente de la cache,
entonces la memoria principal debe actualizarse, rescribiendo la línea de cache en el
bloque de memoria antes de transferir el nuevo bloque.
Pero se nos presentan ciertos problemas. Primero, más de dispositivo puede tener
acceso a la memoria principal como por ejemplo un módulo de entrada/salida puede
escribir/leer directamente en/de memoria. Si una palabra ha sido modificada solo en la
cache, la correspondiente palabra de memoria no es válida. Además, si el dispositivo
de E/S ha alterado la memoria principal, entonces la palabra de cache no es válida.
Para evitar estos problemas, se nos presentan distintas técnicas:
 Escritura inmediata: todas las operaciones de escritura se hacen tanto en cache
como en memoria principal, asegurando que el contenido de la memoria principal
siempre es válido.
 Post-escritura: minimiza las escrituras en memoria. Con esta técnica, las
actualizaciones se hacen solo en la cache. Cuando ocurre una actualización, se activa
un bit ACTUALIZAR asociado a la línea. Después, cuando el bloque es sustituido, es
(post) escrito en la memoria principal si y solo si el bit ACTUALIZAR está activo.

6.6 Correspondencias
Ya que hay menos líneas de cache que bloques de memoria principal, se necesita un
algoritmo que haga corresponder bloques de memoria principal a líneas de cache.
Además, se requiere algún medio para determinar que bloque de memoria principal
ocupa actualmente una línea dada de cache. La elección de la función de
correspondencia determina cómo se organiza la cache. Pueden utilizarse tres
técnicas: directa, asociativa y asociativa por conjuntos.

A manera de resumen, tenemos que en el primer caso un bloque de memoria principal


(Mp) solo puede ubicarse en una línea de la cache (Mc); en el segundo caso, un
bloque puede ubicarse en cualquier línea de la memoria cache y finalmente, el último
caso es una combinación de los dos anteriores.

6.6.1 Correspondencia directa


Es la técnica más sencilla que, como dijimos antes, consiste en hacer corresponder
cada bloque de memoria principal a solo una línea posible de cache. La
correspondencia se expresa como:

𝑖 = 𝑗 𝑚𝑜𝑑𝑢𝑙𝑜 𝑚
Dónde:

i=número de línea de cache;


j=número de bloque de memoria principal;
m=número de líneas en la cache.

Esta función se implementa fácilmente utilizando la dirección.


Se conoce como “asociación directa” debido a que cada línea de memoria cache se
corresponde con un conjunto explícito de bloques de memoria principal. En una
memoria cache de asignación directa, cada bloque de memoria principal se asigna a
una única línea, pero cada línea puede recibir más de un bloque. La asignación de los
bloques de memoria principal a las líneas de la memoria cache se realiza a través de
la partición de la dirección en campos asignados a la etiqueta, la línea y la palabra. La
etiqueta es necesaria para diferenciar si un determinado bloque de memoria principal
está cacheado o no, ya que a varios bloques de memoria principal les corresponde un
mismo bloque en cache y por tanto si no fuera por los bits de etiqueta sería imposible
diferenciar qué bloque de memoria principal se hace referencia.

Este tipo de correspondencia es poco costosa de implementar. Su principal desventaja


es que hay una posición concreta de cache para cada bloque dado. Por eso, si un
programa hace referencia repetidas veces a palabras de dos bloques diferentes
asignados en la misma línea, dichos bloques se estarían intercambiando
continuamente en la cache y la tasa de aciertos seria baja.

6.6.2 Correspondencia asociativa

La correspondencia asociativa supera la desventaja de la directa, permitiendo que


cada bloque de memoria principal pueda cargarse en cualquier línea de la cache. En
este caso, la lógica de control de la cache interpreta una dirección de memoria
simplemente como una etiqueta y un campo de palabra. El campo de etiqueta
identifica unívocamente un bloque de memoria principal. Para determinar si un bloque
está en la cache, su lógica de control debe examinar simultáneamente todas las
etiquetas de líneas para buscar una coincidencia.

Con este tipo de correspondencia, hay flexibilidad para que cualquier bloque sea
reemplazado cuando se va a escribir uno nuevo en la cache. La principal desventaja
de la correspondencia asociativa es la compleja circuitería necesaria para examinar en
paralelo las etiquetas de todas las líneas de cache.
Si alguna etiqueta de la memoria de etiquetas coincide con el campo de etiquetas de
la referencia a memoria principal, se extrae la palabra de la línea desde la posición
indicada por el campo de palabra. Si la palabra a que se hizo referencia no se
encuentra en la memoria cache, se deberá traer desde la memoria principal el bloque
de memoria que contiene la palabra buscada, recuperando luego esa palabra referida
desde la memoria cache.

6.6.3 Correspondencia asociativa por conjuntos

La correspondencia asociativa por conjuntos es una solución de compromiso que


recoge lo positivo de las correspondencias directa y asociativa, sin presentar sus
desventajas. En este caso, la cache se divide en v conjuntos, cada uno de k líneas.
Las relaciones que se tienen son:

𝑚=𝑣∗𝑘

𝑖 = 𝑗 𝑚𝑜𝑑𝑢𝑙𝑜 𝑘

Dónde:
i=número de conjunto de cache
j=número de bloque de memoria principal
m=número de líneas de la cache

La asignación asociativa por conjuntos es más practica que la asignación


completamente asociativa debido a que la porción asociativa queda limitada a solo
algunas líneas que forman un conjunto.

6.7 Políticas de reemplazo


Una vez que se ha llenado la cache, para introducir un nuevo bloque debe sustituirse
uno de los bloques ya existentes. Para el caso de correspondencia directa, solo hay
una posible línea para cada bloque particular y no hay elección posible. En cambio,
para las técnicas de correspondencia asociativa se requieren políticas de reemplazo,
también llamadas algoritmos de sustitución.
Los algoritmos de sustitución, son programas que buscan optimizar la gestión de la
información en la memoria cache del ordenador. Cuando el cache está lleno, el
algoritmo elije que elementos elimina para liberar espacio y poder añadir nuevos
elementos.
Se han probado diversos algoritmos, entre ellos los siguientes:

 LRU: es el llamado least recently used, en español menos usado recientemente.


Se sustituye el bloque que se ha mantenido en la cache por más tiempo sin haber sido
referenciado. Este algoritmo lleva el seguimiento de lo que se va usando, pero esto
resulta caro si se quiere hacer con precisión.
 FIFO: es el llamado first in, first out, en español primero en entrar, primero en salir.
Se sustituye el bloque del conjunto que ha estado más tiempo en la cache.
 LFU: es el llamado least frequently used, en español menos usado frecuentemente.
Se sustituye aquel bloque del conjunto que ha experimentado menos referencias. Se
podría implementar asociando un contador a cada línea.
6.8 Cache multinivel
Cuando se introdujeron originalmente las caches, un sistema tenia normalmente solo
una cache. Pero recientemente, se ha convertido en una norma el uso de múltiples
cache.

A medida que fue creciendo el tamaño de los circuitos integrados de silicio, así como
la densidad de integración de los elementos que lo componen, se hizo posible incluir la
memoria cache en el mismo circuito integrado que el procesador: cache on-chip o
interna.
Esta cache puede ser más rápida que una memoria cache externa, es decir, una
cache off-chip o externa. Sin embargo, la tecnología actual no ofrece la densidad
suficiente como para colocar toda la memoria cache en el mismo circuito integrado del
procesador.
Por este motivo, se desarrollaron la memoria cache de múltiples niveles, siendo los
siguientes:

 Nivel L1 (cache interna): a menudo referida como cache o cache interna principal,
es utilizada para acceder a datos importantes y de uso frecuente. Es la más rápida y
más costosa se integra en el mismo circuito integrado que contiene al procesador,
mientras que el resto de la memoria se coloca fuera de dicho circuito integrado. Las
memorias cache de datos e instrucciones se mantienen separadas en este nivel.
 Nivel L2 (cache externa): se utiliza para almacenar información recientemente
visitada. También es conocida como cache secundaria, está diseñada para reducir el
tiempo necesario para acceder a los datos en los casos en que los datos se hayan
utilizado previamente. Es más lenta que la memoria cache L1. Se integra fuera del
circuito integrado del procesador. Los datos e instrucciones se implementan
unificadas, es decir, la misma memoria contiene tanto datos como instrucciones.

Con la reciente disponibilidad de superficie para cache en el propio chip, en la mayoría


de los microprocesadores modernos se ha llevado la cache L2 al chip del procesador,
y se añade una cache L3. Inicialmente, la cache L3 era accesible a través del bus
externo, pero más recientemente los microprocesadores han incorporado una L3 on-
chip, que se utiliza para alimentar a la cache L2 y generalmente es más rápida que la
memoria principal del sistema pero más lenta que la L2.