martes, 23 de marzo de 2010

Que es la caché

En informática, una cache o caché es un conjunto de datos duplicados de otros originales, con la propiedad de que los datos originales son costosos de acceder, normalmente en tiempo, respecto a la copia en el caché. Cuando se accede por primera vez a un dato, se hace una copia en el cache; los accesos siguientes se realizan a dicha copia, haciendo que el tiempo de acceso medio al dato sea menor.










Un caché es un sistema especial de almacenamiento de alta velocidad. Puede ser tanto un área reservada de la memoria principal como un dispositivo de almacenamiento de alta velocidad independiente.

COMPOSICION INTERNA



Los datos originales son costosos de acceder, normalmente en tiempo, respecto a la copia en el caché. Cuando se accede por primera vez a un dato, se hace una copia en el caché; los accesos siguientes se realizan a dicha copia, haciendo que el tiempo de acceso medio al dato sea menor. El término caché puede utilizarse también para una zona de memoria de disco denominado caché de disco (Disk cache o Cache buffer en inglés).

DISEÑO

En el diseño de la memoria cache se deben considerar varios factores que influyen directamente en el rendimiento de la memoria y por lo tanto en su objetivo de aumentar la velocidad de respuesta de la jerarquía de memoria. Estos factores son las políticas de ubicación, extracción, reemplazo, escritura y el tamaño de la cache y de sus bloques.

Política de ubicación
Decide dónde debe colocarse un bloque de memoria principal que entra en la memoria cache. Las más utilizadas son:
• Directa: Al bloque i-ésimo de memoria principal le corresponde la posición i módulo n, donde n es el número de bloques de la memoria cache.
• Asociativa: Cualquier bloque de memoria principal puede ir en cualquiera de los n bloques de la memoria cache.
• Asociativa por conjuntos: La memoria cache se divide en k conjuntos de bloques, así al bloque i-ésimo de memoria principal le corresponde el conjunto i módulo k. Dicho bloque de memoria podrá ubicarse en cualquier posición de ese conjunto.

Política de extracción
La política de extracción determina cuándo y qué bloque de memoria principal hay que traer a memoria cache. Existen dos políticas muy extendidas:
• Por demanda: Un bloque sólo se trae a memoria cache cuando ha sido referenciado y se produzca un fallo.
• Con prebúsqueda: Cuando se referencia el bloque i-ésimo de memoria principal, se trae además el bloque (i+1)-esimo. Esta política se basa en la propiedad de localidad espacial de los programas.

Política de reemplazo

Determina qué bloque de memoria cache debe abandonarla cuando no existe espacio disponible para un bloque entrante. Básicamente hay tres políticas que son:
• Aleatoria: El bloque es reemplazado de forma aleatoria.
• FIFO: Se usa un algoritmo First In First Out FIFO (primero en entrar es el primero en salir) para determinar qué bloque debe abandonar la cache. Este algoritmo generalmente es poco eficiente.
• Menos recientemente usado (LRU): Se sustituye el bloque que hace más tiempo que no se ha usado en la cache, traeremos a cache el bloque en cuestión y lo modificaremos ahí.
• Menos frecuencias usadas (LFU): Se sustituye el bloque que ha experimentado menos referencias.

ORGANIZACION DE LA CACHÉ

Las memorias caché son elementos básicos en cualquier CPU y GPU actual. Su funcionamiento básico es muy sencillo. Se trata de una tabla. Consta de una serie de marcos en los que se almacenan copias de bloques de la memoria principal. Cada uno de estos marcos va asociado a una etiqueta que permite saber que bloque de memoria se ha copiado en dicho marco. Los datos en una memoria caché pueden organizarse según varios parámetros que afectan a su rendimiento de una manera u otra.

El primer factor importante es el tamaño. En general una caché grande tiene menos fallos (es más probable que los datos pedidos estén en la caché), pero a cambio es lenta, además de que una caché muy grande supone ocupar una superficie del chip considerable.

Otra decisión a tomar es el tamaño de los marcos de la caché. En una caché con marcos pequeños es más fácil que el procesador según vaya pidiendo datos (por ejemplo procesando un array) llegue a pedir alguno que no está en la caché, por lo que hay más probabilidad de tener fallos. Sin embargo, en caso de tener un fallo, copiar un bloque a un marco de la caché es una operación menos costosa que si el marco fuera más grande.

Como hemos visto, las cachés pueden alojar algunos bloques de memoria para poder acceder a ellos rápidamente. Existen estrategias a la hora de emplazar un bloque memoria en un marco de la caché:
emplazamiento directo: A un bloque le corresponde un único marco. Esta estrategia es sencilla, hace que la caché sea rápida, pero provoca más fallos de caché.
emplazamiento asociativo: Un bloque puede almacenarse en cualquier marco. En este caso se minimizan los fallos, pero la caché es más lenta.
emplazamiento asociativo por conjuntos: A un bloque le corresponde un pequeño conjunto de marcos. Es una solución intermedia entre las dos anteriores.

Lo ideal sería poder tener una caché lo más grande posible y lo más rápida posible al mismo tiempo. Tecnológicamente no es posible por lo que se tiende a utilizar varios niveles de caché. Pueden usarse varios niveles de caché que son cada vez más grandes y más lentas. De esta manera el procesador accede a la caché de nivel 1, que es la más rápida, pero la más pequeña. En caso de haber un fallo la información no se busca directamente en la memoria principal, sino que se busca en la caché de nivel 2, que es más lenta, pero aún así sensiblemente más rápida que la RAM. En la actualidad es muy común utilizar 3 niveles de caché. El objetivo es que desde el punto del vista del procesador se vea una memoria del tamaño de la memoria principal (GB) con la velocidad de acceso de la caché de nivel 1 (ns).

En general un procesador puede incluir diferentes cachés diseñadas especialmente para una función específica, lo que hace que tengan sus peculiaridades. Por ejemplo es habitual que existan cachés separadas para de datos y de instrucciones, al menos en el primer nivel, para evitar los riesgos estructurales.

sábado, 20 de marzo de 2010

RIESGOS ESTRUCTURALES

En la actualidad, como ya hemos visto, la mayoría de los procesadores son RISC y su arquitectura se basa en muchos puntos en la arquitectura MIPS, que se ve en la siguiente imagen:


Como se puede ver en la imagen, el procesador está segmentado en 5 etapas, que son:
  1. Emisión de instrucciones
  2. Decodificación de instrucciones
  3. Ejecución
  4. Acceso a memoria
  5. Escritura de resultados
En teoría, un procesador de este tipo podría finalizar una instrucción por ciclo pero en la práctica hay una serie de circunstancias que hacen que no sea así. A estas circunstancias las llamamos riesgos. Veremos 3 tipos de riesgos y qué se puede hacer para evitarlos o minimizarlos.

En primer lugar hay riesgos estructurales. Estos se dan cuando 2 o más instrucciones necesitan utilizar el mismo recurso a la vez. Si por ejemplo intentamos leer una instrucción a la vez que un dato de memoria (LOAD), nos encontramos con un riesgo estructural. Hay varias formas de actuar ante una situación así:
  • Que todas las instrucciones en conflicto menos una esperen a otro ciclo.
  • Replicar recursos.
  • Si el recurso lo permite, establecer turnos de uso dentro de un ciclo.
Por ejemplo, para resolver el riesgo que se ha planteado en el parrafo anterior, los procesadores MIPS duplican la memoria, pasando a tener una de instrucciones y una de datos. Cada solución tiene su inconveniente. Si hacemos que las instrucciones esperen, el procesador está perdiendo rendimiento. Si replicamos recursos, la fabricación será más cara. Si establecemos turnos, el recurso debe ser lo suficientemente rápido para relizar varias operaciones por ciclo, lo que seguramente aumente la complejidad y el precio.

El segundo tipo de riesgos que nos podemos encontrar son los riesgos de datos y son de alguno de estos 3 tipos:
  • RAW (Read After Write): Se produce cuando una instrucción necesita el resultado de una anterior que aún no se ha computado. Por ejemplo:
ADD R3,R1,R4
SUB R9,R3,R7
  • WAR (Write After Read): Sucede cuando una instrucción escribe en un registro que lee una instrucción anterior, como en este ejemplo:
ADD R3,R1,R4
SUB R1,R7,R8

Si la 2ª instrucción termina antes de que la 1ª lea sus operandos, el valor de R1 será incorrecto.
  • WAW (Write after Write): Se produce cuando una instrucción escribe en un registro en el que también escribe otra instrucción anterior, como en este ejemplo:
ADD R3,R1,R4
SUB R3,R8,R5

En este caso, si la 2ª instrucción termina antes que la primera, cuando esta lo haga modificará el valor de R3 incorrectamente.
Para evitar estos riesgos, se pueden utilizar las siguientes técnicas:
  • Se puede parar la ejecución hasta que la instrucción correspondiente haya terminado
  • Si nos fijamos en el diagrama del principio, tras la fase de ejecución ya podemos tener el resultado de la operación por si una posterior lo necesita. Si modificamos el procesador para conectar la salida de la ejecución directamente con la decodificación de instrucciones, podemos minimizar los riesgos RAW. Esto está implementado en los procesadores MIPS.
  • Como no todas las instrucciones tienen dependencias entre sí, podemos reordenarlas en tiempo de compilación de manera que las que sí tienen dependencias estén los más separadas que se pueda. De esta manera se minimizan los riesgos vistos anteriormente.
El último tipo de riesgos son los riesgos de control. Aparecen cuando hay un salto condicional. La resolución del salto no es inmediata, por lo que no sabemos cual es la siguiente instrucción hasta que la instrucción pase por la fase de ejecución. Esto hace que el procesador tenga que pararse momentáneamente. Para mitigar esto podemos hacer lo siguiente:
  • Como ya hemos dicho, una posibilidad es pararse hasta que se resuelva el salto
  • El procesador predice si se salta o no. En caso de acertar no hay penalización. Si no, el resultado es el mismo que si se hubiera parado.
  • Se añade lógica a la fase de decodificación de instrucción para saber si se toma el salto lo antes posible. De todas formas en esta arquitectura habría un ciclo en el que todavía no se ha resuelto el salto. Para evitar perderlo, ese ciclo se utiliza para ejecutar (si es posible) una instrucción que no dependa del salto. Esto último puede realizarlo el procesador o el compilador.
Aunque en todos los casos parar la ejecución, o lo que es lo mismo intercalar instrucciones NOOP (no operation) en el flujo de ejecución evita todos los riesgos, esta solución siempre reduce el rendimiento del procesador y hay que recurrir a otras técnicas que añaden más o menos complejidad al procesador. Más adelante veremos cómo en la práctica las técnicas que se utilizan son más complejas que las descritas y los procesadores son capaces de reordenar las instrucciones dinámicamente para evitar los riesgos que hemos visto, evitando las paradas y la pérdida de rendimiento que conllevan.


Evolucion

Evolución De La Cache 
La memoria caché

Desde la aparición en el mercado de procesadores con frecuencia de reloj de 25 o incluso 33 MHz o mas, una memoria de trabajo constituida por RAM dinámica ya no esta preparada para satisfacer las exigencias de la CPU en términos de tiempo de acceso.

Con esas frecuencias, el procesador se ve forzado a aguardar continuamente hasta que la memoria de trabajo reaccione, lo cual conlleva que su capacidad operativa no sea aprovechada al máximo.

En principio, la memoria de trabajo debería poder ser sustituida completamente por componentes estáticos de RAM que permitiesen intervalos de acceso bastante más breves.

Pero esto seria demasiado caro. Por eso, en los casos en relación a equipos 386 y 486 de altas frecuencias, se ha recurrido a un método que ya se utilizaba en las gigantescas computadoras de los años setenta:

 la instalación de una RAM cache externa. "Externa" quiere decir, en este contexto, que se sitúa fuera de la CPU, en su entorno y unida a ella por el sistema bus.

En los 486, la memoria caché, que estamos describiendo recibe también el nombre de "caché, de segundo nivel", se ubica físicamente sobre la placa madre y consta de una serie de componentes est ticos de RAM con una capacidad de 64 o 256 kilobits.

Así pues, con este procedimiento pueden obtenerse cachés de 64 o 256 kilobytes, tamaño bastante inferior al de la memoria de trabajo. La vigilancia de la memoria caché corre a cargo del controlador caché 82385 de Intel.