Simulador de Memoria Caché SMPCache 1.0
Simulador de Memoria Caché SMPCache 1.0
1/28
Simulador SMPCache 1.0
Símbolo Descripción
A = Acierto Un acierto es un acceso con éxito a la caché.
F = Fallo Un fallo se produce cuando la información buscada no se encuentra en
caché.
FA = Frecuencia de aciertos Es el % de aciertos en accesos a caché.
FF = Frecuencia de fallos FF=1-FA; Tiene un significado análogo.
Para un programa: Se cumple:
NA = Número de aciertos. FA=NA/NC
NF = Número de fallos. FF=NF/NC
NC = Nº total de accesos o NC=NA+NF
referencias a memoria.
Tabla 1: Algunas de las variables con las que podemos estudiar el rendimiento de la caché.
MEMORIA PRINCIPAL
Palabras de memoria
Desplazamiento de la palabra en el bloque
0 0 Dirección de la estructura de bloque
1
2
1 MEMORIA CACHÉ
... Etiqueta
Bit de Validez Bloque Palabra
2
0 .V k-1 2 1 0
1 .V
0 3
1 Bloque de k .V
... Palabras
.V
k-1
4
........
...... P-1 .V
M-1
Dirección de memoria: Dir. estructura de bloque Desplazamiento
2n-1 (suministrada por la CPU)
2/28
Simulador SMPCache 1.0
correspondiente) y el bit de validez (bit que indica si el bloque contiene datos válidos).
Llamamos conjunto al grupo de bloques de caché cuyas etiquetas son examinadas en
paralelo.
La dirección de memoria especifica por completo la localización de una palabra dentro
de la memoria principal. Consta de la dirección de la estructura de bloque (que identifica un
bloque dentro de la memoria principal) y la dirección del desplazamiento de bloque (que
posiciona la palabra dentro del bloque). Esta es la dirección de memoria o dirección
suministrada por la CPU. Para “convertirla” a dirección de caché, se interpretará de acuerdo
con la función de correspondencia considerada.
Como ya hemos mencionado, el motivo por el que se agrupan las palabras en bloques es
para aprovechar el principio de localidad espacial. Los bloques son la unidad de información
que van a intercambiarse la memoria principal y la memoria caché (o las cachés entre sí),
mientras la CPU solicita lecturas o escrituras sobre una palabra concreta.
La función de correspondencia es un algoritmo o procedimiento que asigna a los
bloques de la MP posiciones definidas en la caché. Esto es necesario porque existen menos
particiones de caché que bloques en MP. La correspondencia se apoya en una lógica de
asignación de bloques. Son tres las funciones de correspondencia: directa, totalmente
asociativa, y asociativa por conjuntos de n vías. La correspondencia es directa cuando a
cada bloque de MP solamente le corresponde una partición de caché. Es totalmente
asociativa cuando un bloque se puede ubicar en cualquier posición de la caché. Finalmente,
es asociativa por conjuntos de N vías cuando la caché se organiza en un número de
conjuntos de N bloques; entonces un bloque de MP se corresponde con un conjunto,
pudiéndose ubicar en cualquiera de los bloques que lo componen.
Cuando hay que ubicar un bloque de MP en la caché (reemplazando otro), la
correspondencia nos informa de los posibles conjuntos o bloques donde sustituir. Unos
algoritmos de reemplazo, implementados por hardware, deciden dónde hacer la sustitución
(excepto en el caso de correspondencia directa). Las estrategias comunes son: Aleatoria,
LRU (menos recientemente usado), FIFO (primero en entrar, primero en salir) y LFU
(menos frecuentemente usado).
La operación común de una caché comienza con su inicialización (cuando todos los bits
de validez se ponen a 0). Tras ello, la caché está preparada para que se realicen en ella
operaciones de lectura y escritura. Básicamente, la operación de lectura comienza cuando la
CPU solicita una lectura de memoria. Se lee primero de caché, y si allí no se encuentra la
palabra requerida (fallo de caché), se acude a MP, de donde se lee la palabra, y se emplaza el
bloque que contiene esa palabra en la caché. En una escritura, la CPU pide reemplazar una
porción de bloque (una palabra). Esto implica leer el bloque original, modificar parte de él, y
escribir de nuevo el valor del bloque. Hay dos políticas básicas para escrituras: Escritura
directa (si hay acierto, la información se escribe en el bloque de la caché y en el bloque de la
MP en paralelo), y Post-escritura (si hay acierto, la información se escribe sólo en el bloque
de la caché, el bloque modificado se escribe en MP sólo cuando vaya a ser reemplazado).
Los fallos de caché se pueden clasificar en forzosos (cuando el primer acceso a un
bloque no está en la caché, y debe llevarse a la misma), de capacidad (cuando la caché no
tiene capacidad suficiente para contener todos los bloques necesarios de un programa,
produciéndose fallos debido a los bloques que continuamente se reemplazan) y de conflicto
(cuando a un bloque de caché se le asocian demasiados bloques de MP, generándose fallos de
colisión).
3/28
Simulador SMPCache 1.0
2. Función de correspondencia.
La función de correspondencia es un algoritmo que establece una relación entre los
bloques de memoria principal y las posiciones que van a ocupar en las cachés.
Básicamente, las funciones de correspondencia se van a englobar en uno de los
siguientes tipos, aunque existen otras formas de realizarla. Estos son:
• Correspondencia directa.
• Correspondencia totalmente asociativa.
• Correspondencia asociativa por conjuntos.
Estas son, por otro lado, las funciones de correspondencia que el usuario puede
seleccionar dentro de este simulador.
La memoria caché dispone para cada bloque de una serie de bits adicionales que nos
dan información acerca de su estado, etc. Como un bloque de memoria caché puede contener
diferentes bloques de memoria principal, necesitaremos saber cuál es el que se encuentra
almacenado en cada momento. Para ello, se hace uso de una etiqueta que estará constituida
por una serie de bits que nos permitan identificarlo de forma única.
Para comprobar si un bloque se encuentra en la caché, habrá que comparar las diferentes
etiquetas con una obtenida a partir de la dirección deseada, produciéndose un acierto en el
caso de que alguna coincida. Estas comparaciones son normalmente realizadas en paralelo, lo
que supone una mayor complejidad hardware.
No existe una forma determinada para establecer la etiqueta y como veremos a
continuación existen diferentes estrategias.
POS = D módulo N
Donde:
• POS es la posición que ocupará el bloque dentro de la memoria caché.
• D es la dirección del bloque de memoria principal.
• N es el número de bloques que tiene la caché.
4/28
Simulador SMPCache 1.0
El desplazamiento será el mismo que el que tenga la dirección del bloque de memoria
principal, ya que el tamaño de los bloques es igual, tanto en memoria principal como en
caché.
El índice es el conjunto de bits de la dirección de bloque de memoria principal, que se
utilizan para obtener la posición que ocupará el bloque dentro de la caché. No es necesario
que ésta se obtenga a partir de todos los bits de la dirección de bloque. Bastará con que el
conjunto de bits seleccionados sea igual que el número de bits necesarios para direccionar
todos los bloques de caché.
La etiqueta será el resto de bits de la dirección de bloque de memoria principal, que no
se han utilizado como índice. Son los bits que se comparan a la hora de determinar si un
bloque se encuentra en caché o no.
La Figura 2 muestra un esquema de correspondencia directa.
Las principales ventajas de esta técnica son su simplicidad y bajo coste. Su principal
desventaja se produce en el caso de que se haga uso continuo de dos bloques de memoria que
ocupen la misma posición en la caché, se producirán fallos de caché (fallos de conflicto) cada
vez que se haga uso de ellos.
Para este tipo de correspondencia, no es necesaria la implantación de una función de
reemplazamiento en el sistema, puesto que ya sabemos de antemano cuál va a ser el bloque a
sustituir.
5/28
Simulador SMPCache 1.0
Etiqueta Desplazamiento
La ventaja de este sistema es que un bloque puede ser asignado en cualquier posición.
Entre sus desventajas cabe destacar que las búsquedas son más complejas y requieren de una
circuitería adicional, ya que se deben realizar las comparaciones de las etiquetas en paralelo,
en todos los bloques de caché.
6/28
Simulador SMPCache 1.0
En este caso, la dirección de caché sería igual que en la correspondencia directa, con la
diferencia de que el índice se refiere a un conjunto en lugar de a un bloque:
7/28
Simulador SMPCache 1.0
3. Algoritmo de reemplazamiento.
Su función es la de seleccionar un bloque de caché de entre un grupo de ellos, de
acuerdo a un determinado criterio que va a depender del método de reemplazamiento
utilizado. Este algoritmo es muy importante y habrá que usarlo cada vez que haya que
sustituir un bloque de caché por otro.
La función de reemplazamiento sólo tiene sentido cuando se utilizan funciones de
correspondencia asociativa por conjuntos o totalmente asociativa, ya que si estamos utilizando
correspondencia directa, solamente existiría un único bloque candidato para ser sustituido.
A medida que va aumentando el tamaño de la caché, la función de reemplamiento tiene
una menor importancia, porque la tasa de aciertos va a ser muy alta.
Existen una gran diversidad de funciones de reemplazamiento. Las más utilizadas son:
• Aleatoria.
• LRU.
• FIFO.
• LFU.
De entre todas ellas, las más utilizadas son la aleatoria y la LRU, siendo ésta última
bastante mejor que la aleatoria, cuando los tamaños de caché son pequeños.
8/28
Simulador SMPCache 1.0
frecuencia se debe ir recalculando cada vez que se realice una operación en caché, lo que hace
que este método tenga un coste adicional elevado.
La frecuencia de uso se suele calcular dividiendo el número de veces que se ha usado un
bloque por el tiempo que hace que entró en caché.
P1 Pn P1 Pn
Conmutador
Caché Caché
Caché
Bus
P1 Pn
P1 Pn
Caché Caché
Caché Caché
9/28
Simulador SMPCache 1.0
10/28
Simulador SMPCache 1.0
11/28
Simulador SMPCache 1.0
P1 P2 P3
u=? u=? u=7
4 3
Caché Caché Caché
u=5 u=5
5
La figura muestra tres procesadores con cachés conectadas por un bus a una memoria
principal compartida. Se realiza por parte de los procesadores una serie de accesos a la
posición u. Primero, el procesador P1 lee u, trayendo una copia a su caché. Después el
procesador P3 lee u, con lo que también pone una copia en su caché. Tras esto, el procesador
P3 escribe en la posición u cambiando su valor de 5 a 7. Con una caché de escritura directa,
esto causaría que la posición en memoria principal se actualizara; sin embargo, cuando el
procesador P1 vuelve a leer la posición u (acción 4), desafortunadamente leerá el valor
obsoleto (5) de su propia caché en lugar del valor correcto (7) de la memoria principal. La
situación es incluso peor si las cachés son de post-escritura, ya que la escritura de P3 podría
simplemente establecer el bit de modificado asociado con el bloque de caché que mantiene la
posición u, y no actualizaría la memoria principal directamente. Sólo cuando este bloque de
caché sea posteriormente reemplazado de la caché de P3, su contenido sería escrito en la
memoria principal. No sólo P1 leerá el valor obsoleto, sino que cuando el procesador P2 lea
la posición u (acción 5), no la encontrará en su caché y leerá el valor obsoleto de 5 de la
memoria principal, en lugar del 7. Finalmente, si múltiples procesadores escriben distintos
valores para la posición u en sus cachés de post-escritura, el valor final que quedará en la
memoria principal se determinará por el orden en el que los bloques de caché que contienen la
posición u se reemplazan, y no tendrá nada que ver con el orden en el que las escrituras de la
posición u ocurrieron.
Claramente, el comportamiento que acabamos de describir viola nuestra noción intuitiva
de lo que la memoria debería hacer. A diferencia de las E/S, las lecturas y escrituras de
variables compartidas se espera que sean operaciones frecuentes en multiprocesadores; es la
forma en la que múltiples procesos pertenecientes a una aplicación paralela se comunican
entre sí, por lo que no nos convienen las soluciones planteadas para el caso de la coherencia
en E/S (desactivación de la caché, etc.). Dicho de otro modo, no nos convienen los esquemas
de coherencia caché basados en software. En su lugar, nos hemos centrado en los esquemas
de coherencia caché basados en hardware, es decir, la coherencia de caché necesita ser tratada
como un asunto básico en el diseño del hardware. Por ejemplo, las copias de caché obsoletas
de una localización compartida deben eliminarse cuando esa localización se modifica, ya sea
invalidándolas o actualizándolas con el nuevo valor. Dentro de los esquemas de coherencia
caché basados en hardware podemos diferenciar entre arquitecturas de red con caché
coherente y protocolos de coherencia caché. Las arquitecturas de red proponen
12/28
Simulador SMPCache 1.0
multiprocesadores con una jerarquía de buses, en los que el tráfico de la red se reduce
mediante protocolos de coherencia caché jerárquicos. Estas arquitecturas quedan fuera de
nuestros objetivos, pues se alejan de lo que hemos definido como SMP con memoria
compartida por bus, más bien son una combinación de varios de estos SMPs. Sin embargo, si
hemos estudiado detenidamente el concepto de protocolo de coherencia caché. Hay dos clases
de protocolos para mantener la coherencia caché de múltiples procesadores:
• Basados en directorio: La información sobre un bloque de memoria física se
mantiene en una única posición.
• Espionaje (snooping): Cada caché que tiene una copia de datos de un bloque
de memoria física también tiene una copia de la información sobre él. Estas
cachés se utilizan habitualmente en sistemas de memoria compartida con un
bus común, es decir, en los que se centra este simulador.
13/28
Simulador SMPCache 1.0
P1 Pn
Caché Caché
Transacción
“Espionaje” del bus caché-memoria
Dispositivos E/S
Memoria
El controlador de caché que “espía” también realizará cierta acción si una transacción
del bus le es relevante, es decir, implica un bloque de memoria del cual tiene una copia en su
caché. De hecho, como la asignación y reemplazamiento de datos en cachés se gestiona con
granularidad de un bloque de caché (generalmente con longitud de varias palabras) y las
búsquedas fallidas en caché son de bloques de datos, la mayoría de las veces la coherencia
también se mantiene con la granularidad de un bloque de caché. Es decir, o bien un bloque
entero de caché está en un estado válido o no lo está todo él. Por tanto, el bloque de caché es
la granularidad (unidad) de asignación de caché, de transferencia de datos entre cachés y de
coherencia.
El ejemplo más simple de mantenimiento de la coherencia es un sistema que posee
cachés de un solo nivel y escritura directa. Es básicamente la aproximación seguida por los
primeros SMPs basados en buses comerciales a mediados de los 80. En este caso, cada
instrucción de almacenamiento causa que aparezca una transacción de escritura en el bus, por
lo que cada caché observa todo almacenamiento. Si una caché que está espiando tiene una
copia del bloque, invalida (o actualiza) su copia. La siguiente vez que acceda al bloque, verá
el valor más reciente escrito sobre el bus. La memoria siempre contiene datos válidos, por lo
que la caché no necesita realizar ningún tipo de acción cuando observa una lectura en el bus.
En general, un esquema de coherencia de caché basado en la técnica de espionaje del
bus asegura que:
• Todas las transacciones “necesarias” aparecen en el bus.
• Cada caché monitoriza el bus para en las transacciones que le sean relevantes
tomar las acciones oportunas.
El chequeo para determinar si una transacción del bus es relevante para una caché es
esencialmente la misma comparación de etiquetas (de bloques de caché) que se realiza para
una petición (de datos) por parte del procesador. La acción adecuada podría implicar invalidar
o actualizar el contenido o estado de ese bloque de memoria, y/o suministrar el último valor
para ese bloque de memoria desde la caché al bus.
Un protocolo de espionaje de coherencia de caché une dos facetas básicas de la
arquitectura del computador: las transacciones en el bus y el diagrama de transición de
14/28
Simulador SMPCache 1.0
estados asociado con un bloque de caché. Recuerde que una transacción en el bus consiste en
tres fases: arbitración, comando/dirección y datos. En la fase de arbitración, los dispositivos
que desean realizar (o mandar) una transacción indican su petición del bus y el árbitro del bus
selecciona una de éstas y responde mediante su señal de asignación del bus. Tras la
asignación, el dispositivo coloca el comando, por ejemplo leer o escribir, y la dirección
asociada en las líneas de control y dirección del bus. Todos los dispositivos observan la
dirección y uno de ellos reconece que es el responsable para esa dirección particular. Para una
transacción de lectura, la fase de dirección viene seguida con la transferencia de datos. Las
transacciones de escritura varían de un bus a otro en que los datos se transfieran durante o
después de la fase de dirección. Para muchos buses, el dispositivo esclavo (servidor) puede
introducir una señal de espera para retener la transferencia de datos hasta que esté preparado.
Esta señal de listo es diferente de cualquier otra señal del bus, porque es un OR-cableado a
través de todos los procesadores, es decir, es un 1 lógico si cualquier dispositivo la emite. El
dispositivo maestro (cliente) no necesita saber qué dispositivo esclavo está participando en la
transferencia, sólo si hay alguno y está listo.
La segunda noción básica es que cada bloque en una caché de uniprocesador tiene un
estado asociado, junto con la etiqueta y los datos, que indica la disposición del bloque, por
ejemplo, no válido, válido, modificado. La política de caché se define por el diagrama de
transición de estados de un bloque de caché. Las transiciones de un bloque suceden cuando se
accede a una dirección dentro del bloque. Para una caché de escritura directa y sin asignación-
en-escritura (no-write-allocate), sólo se necesitan dos estados: válido y no válido.
Inicialmente todos los bloques son no válidos (lógicamente, todos los bloques de memoria
que no están residentes en caché pueden verse como que se encuentran en el estado “no
válido”). Cuando un procesador produzca un fallo de caché en una operación de lectura, se
generará una transacción en el bus para cargar el bloque desde la memoria y el bloque se
marcará como válido. Las escrituras generan una transacción en el bus para actualizar la
memoria y el bloque de caché si está presente en el estado válido. Las escrituras nunca
cambian el estado del bloque (si un bloque se reemplaza, podría marcarse como no válido
hasta que la memoria proporcione el nuevo bloque, con lo cual vuelve a ser válido). Una
caché de post-escritura necesita un estado adicional, indicando si un bloque está modificado o
“sucio”.
En un esquema de espionaje para coherencia de caché, cada controlador de caché recibe
dos conjuntos de entradas: las peticiones de memoria invocadas por el procesador, y las
informaciones espiadas en el bus sobre transacciones de otras cachés. En respuesta a estas
entradas, el controlador actualiza el estado del bloque apropiado en la caché; Responde al
procesador con los datos solicitados, posiblemente generando nuevas transacciones en el bus
para obtener los datos; Responde a las transacciones en el bus generadas por otros
actualizando su estado y, a veces, interviene completando la transacción en curso. El
protocolo de espionaje es, por tanto, un algoritmo distribuido representado por una colección
de esas máquinas de estado finitas que cooperan. Este protocolo se especifica mediante los
siguientes componentes:
1. El conjunto de estados asociados con los bloques de memoria en las cachés
locales.
2. El diagrama de transición de estados que toma como entradas el estado actual y
la petición del procesador o la transacción en el bus observada, y produce como
salida el siguiente estado para el bloque de caché.
3. Las acciones reales asociadas con cada transición de estado, que se determinan
en parte por el conjunto de acciones factibles definidas según el diseño del bus,
15/28
Simulador SMPCache 1.0
la caché y el procesador.
PrWr / BusWr
Figura 8. Coherencia mediante espionaje para un multiprocesador con cachés de escritura directa y sin
asignación-en-escritura (no-write-allocate).
Como en el caso uniprocesador, cada bloque de caché tiene sólo dos estados: no válido
(I, de inválido) y válido (V). Las transiciones están etiquetadas con la entrada causante de la
transición y la salida generada con la transición (la notación A/B significa que si observas A
entonces generas la transacción B). Desde el punto de vista del procesador, las peticiones
pueden ser de lectura (PrRd) o escritura (PrWr). Desde el punto de vista del bus, el
controlador podría observar/generar transacciones en el bus de lectura (BusRd) o escritura
(BusWr). Por ejemplo, cuando en una petición de lectura del procesador (PrRd) se produce un
fallo en caché (bloque no válido), se genera una transacción BusRd, y tras completar esta
transacción el bloque pasa al estado “válido”. Siempre que el procesador solicite una escritura
(PrWr) en una posición, se genera una transacción en el bus (BusWr) que actualiza esa
posición en la memoria principal sin cambiar el bloque de estado. La mejora clave respecto al
diagrama de estados de un uniprocesador es que cuando el “espía” (vigilante) del bus observa
una transacción de escritura para un bloque de memoria que se encuentra en la caché local,
establece el estado de caché para ese bloque a no válido descartando así su copia. La figura
muestra estas transiciones inducidas por el bus con línea punteada. Por extensión, si cualquier
procesador genera una escritura para un bloque que está en la caché de cualquier otro, todos
los otros invalidarán sus copias del bloque. La colección de cachés implementa de esta forma
una disciplina de un único escritor, múltiples lectores.
El problema de la aproximación de escritura directa es que cada instrucción de
almacenamiento va a la memoria, motivo por el que los microprocesadores más modernos
16/28
Simulador SMPCache 1.0
17/28
Simulador SMPCache 1.0
los otros procesadores se actualizan con una única transacción en el bus, por tanto,
conservando el ancho de banda cuando hay varios procesadores que comparten el bloque. Por
contra, con los protocolos basados en invalidación, en una operación de escritura el estado de
caché de ese bloque de memoria se establece a no válido en todas las otras cachés. Las
escrituras subsiguientes a ese bloque por el mismo procesador no crean tráfico adicional en el
bus, hasta que el bloque es leído por otro procesador. Esto es interesante cuando se espera que
un único procesador realice múltiples escrituras sobre el mismo bloque de memoria antes de
que otros procesadores lean los contenidos de ese bloque de memoria. En general, las
estrategias basadas en invalidación se han mostrado más robustas y son por tanto
proporcionadas como el protocolo por defecto por la mayoría de vendedores. Algunos
vendedores proporcionan un protocolo de actualización como una opción a ser usada
selectivamente para bloques que correspondan a páginas o estructuras de datos concretas.
Las elecciones realizadas respecto al protocolo y estrategias de caché con actualización
frente a invalidación afectan directamente a la selección de estados, el diagrama de transición
de estados, y las acciones asociadas. Se dispone, por tanto, de una flexibilidad sustancial para
la arquitectura del computador en las tareas de diseño a este nivel. En lugar de estudiar todas
las posibles elecciones, hemos considerado los tres protocolos de coherencia habituales, que
mostrarán las opciones de diseño:
• El protocolo de 3 estados MSI.
• El protocolo de 4 estados MESI.
• El protocolo de 4 estados Dragon.
18/28
Simulador SMPCache 1.0
(posiblemente otra caché) suministra los datos. Esta transacción se genera por
una PrRd que falla en la caché, y el procesador espera una respuesta de datos
como resultado de la misma.
• Lectura exclusiva (BusRdX): El controlador de caché pone la dirección en el
bus y solicita una copia exclusiva del bloque con la intención de modificarlo.
El sistema de memoria (posiblemente otra caché) suministra los datos. Todas
las otras cachés necesitan invalidar su posible copia. Esta transacción se genera
por un PrWr a un bloque que no está en su caché o está en la caché pero no en
el estado modificado. Una vez que la caché obtiene la copia exclusiva, la
escritura (PrWr) puede realizarse en la caché. El procesador podría requerir un
asentimiento (reconocimiento) como resultado de esta transacción.
• Post-escritura (BusWB): El controlador de caché pone la dirección y el
contenido para un bloque de memoria en el bus. La memoria principal se
actualiza con el último contenido. Esta transacción se genera por el controlador
de caché en una post-escritura; el procesador no tiene conomiento de la misma,
y no espera una respuesta.
PrRd / -- PrWr / --
PrWr / BusRdX
BusRd / Vaciar
PrRd / -- BusRdX / --
PrRd / BusRd
BusRd / --
19/28
Simulador SMPCache 1.0
Los estados se han puesto de manera que cuanto más cercanos estén a la parte superior
indican que el bloque está asociado más estrechamente con el procesador en cuestión. La
notación A/B significa que si observamos proveniente del procesador o el bus un evento A,
entonces además del cambio de estado, generaremos la transacción en el bus o acción B. “--”
indica la acción nula. Si un arco tiene asociado múltiples pares A/B, simplemente indica que
múltiples entradas pueden causar la misma transición de estados. Una lectura del procesador
(PrRd) a un bloque no residente en caché (“no válido”) causa una transacción BusRd que
sirve ese bloque. El bloque que se acaba de ubicar en caché pasa del estado no válido (I) al
estado compartido (S), exista o no cualquier otra caché que mantenga una copia del mismo
bloque. Cualquier otra caché con el bloque en el estado compartido (S) observa el BusRd,
pero no realiza ninguna acción especial, permitiendo que la memoria responda con los datos.
Sin embargo, una caché con el bloque en el estado modificado (sólo puede haber una) debe
involucrarse en la transacción, ya que la copia de memoria está obsoleta. Esa caché “vaciará”
(pondrá) los datos del bloque en el bus, en lugar de hacerlo la memoria, y pasará su bloque al
estado compartido (S). Tanto la memoria como la caché solicitante necesitan recoger el
bloque. Esto puede realizarse bien con una transferencia caché-a-caché, o señalando un error
en la transacción de lectura en el bus y generando una transacción de escritura para actualizar
la memoria. En el último caso, la caché original repetirá finalmente su petición y obtendrá el
bloque desde la memoria.
La escritura (PrWr) en un bloque no válido (I) es un fallo de escritura, que se sirve
primero cargando el bloque entero en caché y luego modificando los bytes deseados dentro
del mismo. Los fallos de escritura generan una transacción de lectura exclusiva en el bus
(BusRdX), que causa que todas las otras copias del bloque en caché sean invalidadas, por
tanto otorgando a la caché solicitante la propiedad exclusiva del bloque. El bloque pasará al
estado de modificado (M) y luego será escrito. Si cualquier otra caché solicita posteriormente
un acceso exclusivo, el bloque pasará al estado no válido (I), después de vaciar (poner) la
copia exclusiva en el bus.
La transacción más interesante tiene lugar cuando se escribe (PrWr) sobre un bloque
compartido (S). Se trata de una escritura con éxito (en caché) y tradicionalmente podría
servirse completamente por la caché en un uniprocesador. Sin embargo, para mantener la
coherencia se debe generar una transacción en el bus, que haga la escritura visible a los otros
procesadores. Por eso se trata esencialmente como un fallo de escritura, usando una
transacción de lectura exclusiva (BusRdX) para adquirir la posesión del bloque. En este caso,
los datos que se obtienen en la lectura exclusiva generalmente pueden ignorarse, ya que
todavía están en caché. Las escrituras (PrWr) posteriores al bloque mientras esté en el estado
modificado (M) no generarán transacciones en el bus.
Obsérvese que para especificar completamente el protocolo, cada estado en el diagrama
debe tener arcos de salida con las etiquetas correspondientes a todos los eventos observables
(las entradas desde la caché y el bus), y también las acciones asociadas a éstos. Algunas veces
las acciones pueden ser nulas, y en ese caso, podríamos especificar explícitamente las
acciones nulas (véase los estados S y M en la figura), o podríamos simplemente omitir esos
arcos en el diagrama (véase el estado I en la figura). Además, en un fallo de caché, cuando se
trae el bloque de memoria nuevo, las transiciones de estado se hacen como si el estado previo
del bloque fuera el estado no válido (I). Un reemplazamiento, lógicamente, pasa un bloque de
caché al estado no válido al quitarlo de la caché. Los reemplazamientos no aparecen en la
figura, porque se deben a fallos de caché sobre un bloque diferente que cae dentro del mismo
conjunto de caché. La transición de reemplazamiento desde M a I genera una transacción de
post-escritura. En esta transacción las otras cachés no tienen que realizar ningún tipo de
20/28
Simulador SMPCache 1.0
acción especial.
Para ilustrar algunas de las elecciones implícitas de diseño que se han realizado en el
protocolo, vamos a examinar más a fondo la transición desde el estado M cuando se observa
un BusRd para ese bloque. En la Figura 9 la transición nos lleva al estado S y el contenido del
bloque de memoria se coloca en el bus. Mientras que es imprescindible que el contenido se
coloque en el bus, podríamos en lugar de ir al estado S ir al I. La elección de ir al estado S
frente al I refleja la aseveración del diseñador de que es más probable que el procesador
original continúe leyendo ese bloque a que el nuevo procesador escriba dentro de poco en ese
bloque de memoria. Intuitivamente, esta aseveración “apuesta” por los datos
mayoritariamente leídos, que es lo común en muchos programas. Sin embargo, un caso
común donde esto no se cumple es con una bandera o bufer que se utilice para transferir
información de acá para allá entre dos procesos; un procesador escribe en él, el otro lo lee y
modifica, entonces el primero lo lee y modifica, y así sucesivamente. El problema de apostar
por las lecturas compartidas, en este caso, es que cada escritura se precede por una
invalidación, por lo que se incrementa la latencia de la operación de tipo ping-pong. De
hecho, el protocolo de coherencia usado en el primer multiprocesador Synapse hace la
elección alternativa de ir directamente del estado M al I en un BusRd. Algunas máquinas (la
Symmetry de Sequent (modelo B) y la Alewife del MIT) intentan adaptar el protocolo cuando
el patrón de accesos indica datos migratorios de esta forma.
21/28
Simulador SMPCache 1.0
PrWr / --
BusRd / Vaciar
PrWr / BusRdX
BusRd /
PrWr / BusRdX PrRd / -- Vaciar BusRdX / Vaciar
PrRd /
BusRd (¬ S) S BusRdX / Vaciar
22/28
Simulador SMPCache 1.0
La notación es la misma que la seguida para el protocolo MSI. BusRd(S) significa que
cuando ocurrió la transacción de lectura se confirmó la señal “S”, y BusRd(¬ S) significa que
la señal “S” no se confirmó. Un BusRd simple significa que nos da igual el valor de la señal S
para esa transición. Una escritura sobre un bloque en cualquier estado elevará el bloque al
estado M, pero si estaba en el estado E no se requerirá ninguna transacción en el bus.
Observando un BusRd el bloque pasará del estado E al S, ya que existe otra copia en alguna
caché. Nótese que es posible para un bloque estar en el estado S incluso si no existe ninguna
otra copia, pues las copias podrían ser descartadas (S → I) sin notificarlo a otras cachés.
Una pregunta interesante en este protocolo es quién debería suministrar el bloque para
una transacción BusRd cuando tanto la memoria como otra caché tienen una copia del mismo.
En la versión original de Illinois del protocolo MESI la caché, y no la memoria principal,
suministraba los datos. El motivo para esta aproximación era que las cachés se construían con
SRAM, y no DRAM, con lo que podían suministrar los datos más rápidamente. Sin embargo,
esta ventaja era en gran parte mitigada con la complejidad añadida al protocolo - la memoria
debe esperar hasta estar segura de que ninguna caché suministrará los datos antes de tomar el
bus. Si los datos residen en varias cachés, se necesita que exista un algoritmo de selección que
determine cuál proporcionará los datos. Este es el motivo de la notación Vaciar’ en el
diagrama, que indica que el vaciar (poner) el contenido del bloque en el bus sólo se cumple
para ese procesador, los procesadores restantes no realizarán nada. Por otro lado, esta
aproximación es útil en multiprocesadores con memoria distribuida físicamente, porque la
latencia para obtener los datos desde una caché cercana podría ser mucho más pequeña que la
de una unidad de memoria lejana. Este efecto puede ser especialmente importante para
máquinas construidas como una red de nodos SMP, porque las cachés dentro del nodo SMP
podrían suministrar los datos. El multiprocesador DASH de Stanford utilizaba estas
transferencias caché-a-caché por este motivo.
23/28
Simulador SMPCache 1.0
rudimentario; Se proporciona un bit de modo para forzar los fallos (de caché), y el software de
inicialización lee los datos para cada bloque de la caché en el modo de fallo para conseguir
llenarlos).
Las peticiones del procesador, las transacciones en el bus, y las acciones para el
protocolo Dragon son similares a las del protocolo MESI de Illinois. Todavía se asume que el
procesador sólo emite las peticiones de lectura (PrRd) y escritura (PrWr). Sin embargo, dado
que no tenemos un estado no válido en el protocolo, para especificar las acciones cuando se
solicita por primera vez un bloque nuevo de memoria por el procesador, añadimos dos tipos
más de petición: fallo de lectura (PrRdMiss) y fallo de escritura (PrWrMiss) del procesador.
En cuanto a las transacciones en el bus, tenemos la lectura del bus (BusRd), la actualización
del bus (BusUpd), y la post-escritura del bus (BusWB). Las transacciones BusRd y BusWB
tienen el significado normal que se definió para los protocolos MSI y MESI. BusUpd es una
transacción nueva que toma la palabra específica escrita por el procesador y la difunde en el
bus para que todas las otras cachés puedan actualizarse. Difundiendo sólo el contenido de la
palabra modificada en lugar del bloque de caché entero, se espera que el ancho de banda del
bus se utilice más eficientemente. Como en el protocolo MESI, para soportar los estados E y
M, tenemos disponible la señal compartido (S) para el controlador de caché. Esta señal se
emite si existe cualquier procesador, a parte del solicitante, que mantiene en caché el bloque
de memoria referenciado. Finalmente, en cuanto a las acciones, la única capacidad nueva
necesitada es para que el controlador de caché actualice un bloque de memoria en la caché
local (etiquetado como “Actualizar”) con el contenido que se está difundiendo en el bus por
una transacción BusUpd relevante.
La Figura 11 muestra el diagrama de transición de estados para el protocolo de
actualización Dragon.
PrRd / -- PrRd / --
BusUpd / Actualizar
BusRd / --
E SC
PrRdMiss / BusRd(¬ S)
PrRdMiss / BusRd(S)
PrWr / --
PrWr / BusUpd(¬ S)
BusUpd / Actualizar
PrWr / BusUpd(S)
PrWrMiss / BusRd(¬ S)
PrWrMiss / BusRd(S);BusUpd
BusRd / Vaciar
SM M
PrWr / BusUpd(¬ S)
PrRd / --
PrRd / -- PrWr / --
PrWr / BusUpd(S)
BusRd / Vaciar
24/28
Simulador SMPCache 1.0
25/28
Simulador SMPCache 1.0
8. Ficheros de configuración.
Para almacenar la configuración del simulador SMPCache se utilizan ficheros con
extensión .CFG. Estos ficheros serán ficheros de texto con el siguiente formato:
Nº procesadores:
3
Protocolo coherencia caché:
2
Arbitración bus:
1
Ancho palabra (bits):
64
Palabras en un bloque:
128
Bloques en memoria:
1024
Bloques en caché:
64
Función correspondencia:
3
Nº conjuntos:
0
Algoritmo reemplazamiento:
1
Niveles de caché:
1
Política de escritura:
2
Como vemos, en primer lugar se escribe un literal indicando lo que se está configurando
(nº procesadores, protocolo de coherencia, etc.) y en la siguiente línea se establece la
configuración. Todos los ficheros .CFG tendrán el mismo formato, de manera que los
“comentarios” aparecen en las líneas pares, y las configuraciones en sí en las impares.
En el caso de configuraciones numéricas como el nº de procesadores, el ancho de la
palabra, las palabras en un bloque, etc.; Lo que se escribe en el fichero es la propia
configuración numérica. Para el resto de configuraciones se establece una codificación
numérica para cada una de las posibles opciones. La
Tabla 2 muestra las opciones de configuración y su codificación numérica asociada.
26/28
Simulador SMPCache 1.0
etiqueta valor
Donde:
• Etiqueta es un número decimal que identifica el tipo de operación de acceso a
memoria demandada por la CPU en un momento dado: capturar una instrucción
(0), leer un dato de memoria (2) o escribir un dato en memoria (3).
27/28
Simulador SMPCache 1.0
El motivo por el que se agrupan las palabras en bloques es para aprovechar el principio
de localidad espacial. Los bloques son la unidad de información que van a intercambiarse la
memoria principal y la memoria caché (o las cachés entre sí).
28/28