• No results found

encadenadas)

En la estructura de directorio que acabamos de ver, toda la información correspondiente a la coherencia de un bloque de datos —estado del bloque, cuántas copias hay y dónde están— se encuentra centralizada en una palabra en un dispositivo junto a la memoria principal. Eso sí, dado que la memoria principal está distribuida, el directorio también queda distribuido por todos los nodos (procesadores) de la red.

Analicemos una segunda opción para construir directorios. En lugar de guardar en un sitio determinado la información sobre la coherencia de un bloque de datos, esa información se puede repartir por las caches que tienen copias de ese bloque. Por tanto, la información de coherencia de un determinado bloque de datos queda repartida por todo el sistema, pero esa información se enlaza formando con ella listas doblemente encadenadas.

Para construir el directorio de coherencia, hay que añadir la siguiente información en cada procesador:

• En el directorio junto a la memoria principal: una palabra por cada bloque de datos, para almacenar el estado del bloque y la dirección del procesador que tiene la “primera” copia del mismo (un puntero).

estado @copia 1

• En el directorio de la memoria cache: dos direcciones (punteros) por cada bloque, para indicar dónde están la anterior y la siguiente copia del bloque. Además, como es habitual en la cache, se guarda el estado del bloque.

estado @copia i–1 @copia i+1

Los estados de los bloques dependerán del protocolo de coherencia que se implemente (MESI, MOSI...), aunque, como veremos, se van a utilizar más estados para poder gestionar de manera adecuada las listas de copias de los bloques.

En esta figura se muestra una lista de tres copias de un bloque de datos (aunque no aparece en la figura, también se guarda el estado del bloque en el comienzo de la lista y en el directorio de cada cache).

En resumen, no hay una palabra que indique dónde están todas las copias del correspondiente bloque, sino una lista de direcciones distribuida. Además, no hemos limitado el número de copias, ya que la lista puede ser de cualquier tamaño.

La cantidad de memoria que se requiere ahora para el directorio de coherencia es menor que en los casos anteriores. Veamos un ejemplo.

Un sistema MPP tiene 1024 procesadores, cada uno con 128 MB de RAM y 512 kB de cache. Los bloques de datos son de 128 bytes, y se utilizan 3 bits para representar los estados. Compara el tamaño del directorio de coherencia en estos dos casos: (a) directorio junto a MP, con 5 copias máximo; y (b) directorio distribuido en MC.

(a) Número de boques de MP: 1 M

Tamaño de una palabra del directorio: 5 × 10 + 3 = 53 bits Total del directorio en cada nodo: 53 × 1 M → 53 Mb (6,6 MB) Por tanto, el directorio añade un 5% de memoria en cada nodo. (b) Número de bloques en la cache: 4 k

Información de coherencia (por bloque)

En la MC: 2 × 10 + 3 = 23 bits En MP: 10 + 3 = 13 bits Total del directorio en cada nodo: (13 × 1 M + 23 × 4 k) → 13,1 Mb esto es, cuatro veces menos que el anterior.

7.2.2.2.1 Un ejemplo de uso del directorio distribuido en las caches

En un apartado posterior analizaremos más detalladamente cómo se utiliza este tipo de directorios para mantener la coherencia de los datos; pero antes de eso, veamos esquemáticamente, al igual que hemos hecho en el caso anterior, los mensajes de datos y de control que se intercambian los procesadores para mantener la coherencia.

Pj, * Pi,Pk Pi *, Pj bloque de datos bloque de datos bloque de datos bloque de datos Home (memoria principal)

Pi (cache) Pj (cache) Pk (cache)

MP D

MC

▪ Lectura (fallo)

El procesador L quiere leer una palabra de la memoria del procesador H, pero no la tiene en la cache. El procesador R tiene en su cache la única copia del bloque que contiene dicha palabra, en estado coherente. La lista de coherencia de dicho bloque es, por tanto, la siguiente: H → R. Para realizar la operación de lectura se enviarán los siguientes mensajes:

1. L envía un mensaje a H solicitándole el bloque de datos.

2. Al recibir el mensaje, H mira en el directorio; como el bloque de datos no está modificado, enviará a L, desde su MP, el bloque solicitado. Además de ello, actualiza la lista de coherencia del bloque, ya que ahora hay dos copias, para lo que modifica el puntero que contiene el directorio: la nueva cabeza de la lista es L en lugar de R. De paso, junto con el bloque de datos, H envía a L la dirección de la anterior cabeza de la lista de copias del bloque de datos, R.

3. Cuando recibe la respuesta de H, L guarda el bloque en la cache, pero todavía tiene que actualizar la lista de copias, para lo que envía un mensaje a R: a partir de ahora L es la primera copia.

4. Para finalizar la operación, R envía una respuesta a L, indicándole que ya ha actualizado los punteros de la lista de coherencia.

Finalmente, la lista de copias del bloque de datos quedará de la siguiente manera: H → L ↔ R.

▪ Escritura

Por ejemplo, supongamos que se quiere escribir en la copia situada en la cabeza de la lista, que está en estado S. Se trata de un acierto en la cache, por lo que lo único que hay que hacer es eliminar el resto de copias. La operación se realizará de la siguiente manera:

1/2. Se envía un mensaje al nodo H, para que actualice el estado del bloque de datos en el directorio (junto a MP): el estado del bloque pasa de S a M. Como respuesta, H envía a L un mensaje de confirmación de la operación.

3/4. A continuación, L envía un mensaje de invalidación a la segunda copia de la lista (de la que conoce su dirección). Como respuesta, ésta le envía un mensaje de confirmación junto con la dirección de la siguiente copia, que sólo ella conoce.

3'/4'. Se repiten los dos pasos anteriores hasta eliminar todas las copias del bloque de datos.

En resumen. Hemos presentado las principales estructuras que se utilizan para construir directorios de coherencia. En una de ellas, la información de coherencia se concentra en cada nodo en un dispositivo junto a la memoria principal; en la otra, esa información se distribuye por las caches de los procesadores. En el primer caso, el tamaño del directorio puede llegar a ser un problema; en el segundo, la latencia de las operaciones, sobre todo si el número de copias del bloque (la longitud de la lista) es elevado. Sea cual sea la estructura empleada para implementar el directorio, los procesadores van a enviar mensajes de control a través de la red de comunicación, y por tanto es imprescindible procesar esos mensajes de la manera más eficiente posible, ya que forman parte de la ejecución de la operaciones más habituales.