tipos sirve secundario que para memoria informatica importancia definicion caracteristicas caché cache caching memory cpu-architecture processor cpu-cache

caching - sirve - que es cache en informatica



¿Por qué el tamaño de la caché L1 es más pequeño que el de la caché L2 en la mayoría de los procesadores? (7)

¿Por qué el tamaño de la caché L1 es más pequeño que el de la caché L2 en la mayoría de los procesadores?


Creo que la razón principal para esto es que L1-Cache es más rápido y, por lo tanto, más caro.


Hay diferentes razones para eso.

L2 existe en el sistema para acelerar el caso donde hay una falta de caché L1. Si el tamaño de L1 fuera igual o mayor que el de L2, entonces L2 no podría acomodar más líneas de caché que L1, y no podría lidiar con los errores de caché de L1. Desde la perspectiva de diseño / costo, la memoria caché L1 está vinculada al procesador y es más rápida que L2. La idea general de los cachés es que usted acelera el acceso al hardware más lento al agregar un hardware intermedio que es más rentable (y costoso) que el hardware más lento y, sin embargo, más barato que el hardware más rápido que tiene. Incluso si decide duplicar el caché L1, también incrementaría L2, para acelerar los fallos de caché L1.

Entonces, ¿por qué hay caché L2 en absoluto? Bueno, la memoria caché L1 suele ser más rentable y costosa de construir, y está vinculada a un solo núcleo. Esto significa que aumentar el tamaño L1 en una cantidad fija tendrá ese costo multiplicado por 4 en un procesador de doble núcleo, o por 8 en un núcleo cuádruple. Por lo general, L2 se comparte con diferentes núcleos, dependiendo de la arquitectura, se puede compartir en un par o en todos los núcleos del procesador, por lo que el costo de aumentar L2 sería menor incluso si el precio de L1 y L2 fuera el mismo. No lo es.


L1 está acoplado muy estrechamente al núcleo de la CPU, y se accede a él en cada acceso a la memoria (muy frecuente). Por lo tanto, debe devolver los datos realmente rápido (generalmente dentro del ciclo de reloj). La latencia y el rendimiento (ancho de banda) son críticos para el rendimiento de la caché de datos L1. (p. ej., cuatro ciclos de latencia, y admite dos lecturas y una escritura por el núcleo de la CPU en cada ciclo de reloj). Necesita muchos puertos de lectura / escritura para admitir este ancho de banda de alto acceso. Construir un gran caché con estas propiedades es imposible. Por lo tanto, los diseñadores lo mantienen pequeño, por ejemplo, 32 KB en la mayoría de los procesadores de hoy.

Se accede a L2 solo en L1 faltantes, por lo que los accesos son menos frecuentes (generalmente 1/20 del L1). Por lo tanto, L2 puede tener una latencia más alta (por ejemplo, de 10 a 20 ciclos) y tener menos puertos. Esto permite a los diseñadores hacerlo más grande.

L1 y L2 desempeñan papeles muy diferentes. Si L1 se hace más grande, aumentará la latencia de acceso de L1, lo que reducirá drásticamente el rendimiento, ya que hará que todas las cargas dependientes sean más lentas y difíciles de ocultar para la ejecución fuera de orden. El tamaño de L1 es apenas discutible.

Si eliminamos L2, L1 tendrá que pasar al siguiente nivel, digamos memoria. Esto significa que una gran cantidad de acceso irá a la memoria, lo que implicaría que necesitamos más ancho de banda de memoria, que ya es un cuello de botella. Por lo tanto, mantener la L2 alrededor es favorable.

Los expertos a menudo se refieren a L1 como un filtro de latencia (ya que hace que el caso común de L1 llegue más rápido) y a L2 como un filtro de ancho de banda, ya que reduce el uso del ancho de banda de la memoria.

Nota: He asumido una jerarquía de caché de 2 niveles en mi argumento para hacerlo más simple. En muchos de los chips multinúcleo de hoy, hay un caché L3 compartido entre todos los núcleos, mientras que cada núcleo tiene su propio L1 privado y quizás L2. En estos chips, el caché de último nivel compartido (L3) desempeña la función de filtro de ancho de banda de memoria. L2 desempeña el papel de filtro de ancho de banda en el chip, es decir, reduce el acceso a la interconexión en el chip y al L3. Esto permite a los diseñadores usar una interconexión de menor ancho de banda como un anillo y un L3 lento de un solo puerto, lo que les permite hacer que el L3 sea más grande.

Quizás vale la pena mencionar que la cantidad de puertos es un punto de diseño muy importante porque afecta la cantidad de área de chip que consume la memoria caché. Los puertos agregan cables a la memoria caché que consume una gran cantidad de área de chips y energía.


Las otras respuestas aquí proporcionan razones técnicas y específicas por las que L1 y L2 están dimensionadas como están, y si bien muchas de ellas son consideraciones motivadoras para arquitecturas particulares, no son realmente necesarias: la presión arquitectónica subyacente conduce a un aumento de tamaño de caché (privado) a medida que se aleja del núcleo es bastante universal y, en primer lugar, es el mismo que el razonamiento para múltiples cachés.

Los tres hechos básicos son:

  1. Los accesos de memoria para la mayoría de las aplicaciones exhiben un alto grado de localidad temporal, con una distribución no uniforme.
  2. A través de una gran variedad de procesos y diseños, el tamaño de la memoria caché y la velocidad de la memoria caché (latencia y rendimiento) se pueden intercambiar entre sí 1 .
  3. Cada nivel distinto de caché implica un costo incremental de diseño y rendimiento.

Entonces, en un nivel básico, puede ser capaz de decir el doble del tamaño del caché, pero incurrir en una penalización de latencia de 1.4 en comparación con el caché más pequeño.

Entonces, se convierte en un problema de optimización: ¿cuántos cachés debes tener y cuán grandes deberían ser? Si el acceso a la memoria fuera totalmente uniforme dentro del tamaño del conjunto de trabajo, probablemente terminaría con un solo caché bastante grande o sin caché. Sin embargo, el acceso es fuertemente no uniforme, por lo que un caché pequeño y rápido puede capturar una gran cantidad de accesos, desproporcionados a su tamaño.

Si el hecho 2 no existiera, simplemente crearía un caché L1 muy grande y muy rápido dentro de las otras restricciones de su chip y no necesitaría ningún otro nivel de caché.

Si el hecho 3 no existiera, terminaría con una gran cantidad de "cachés" de grano fino, más rápidos y pequeños en el centro, y más lentos y más grandes en el exterior, o tal vez un solo caché con tiempos de acceso variables: más rápido para Las partes más cercanas al núcleo. En la práctica, la regla 3 significa que cada nivel de caché tiene un costo adicional, por lo que generalmente terminas con unos pocos niveles cuantificados de caché 2 .

Otras restricciones

Esto proporciona un marco básico para entender el conteo de caché y las decisiones de tamaño de caché, pero también hay factores secundarios en juego. Por ejemplo, Intel x86 tiene tamaños de página 4K y sus cachés L1 usan una arquitectura VIPT . VIPT significa que el tamaño del caché dividido por el número de formas no puede ser mayor que 3 KiB. Por lo tanto, una memoria caché L1 de 8 vías utilizada en la media docena de diseños de Intel puede tener como máximo 4 KiB * 8 = 32 KiB. Probablemente no sea coincidencia que ese sea exactamente el tamaño del caché L1 en esos diseños. Si no fuera por esta restricción, es totalmente posible que haya visto cachés de L1 de asociatividad más baja y / o más grandes (por ejemplo, 64 KiB, 4 vías).

1 Por supuesto, también hay otros factores involucrados en la compensación, como el área y el poder, pero manteniendo esos factores constantes se aplica la compensación de velocidad de tamaño, e incluso si no se mantiene constante, el comportamiento básico es el mismo.

2 Además de esta presión, existe un beneficio de programación para los cachés de latencia conocida, como la mayoría de los diseños L1: y el programador fuera de orden puede enviar de manera optimista operaciones que dependen de una carga de memoria en el ciclo que el caché L1 devolvería, leyendo el resultado de la red de bypass. Esto reduce la contención y tal vez elimina un ciclo de latencia fuera del camino crítico. Esto pone algo de presión en el nivel de caché más interno para tener una latencia uniforme / predecible y, probablemente, se traduce en menos niveles de caché.

3 En principio, puede usar cachés VIPT sin esta restricción, pero solo si requiere soporte del sistema operativo (por ejemplo, colorear la página) o con otras restricciones. El arco x86 no ha hecho eso y probablemente no pueda comenzar ahora.



lógicamente, la pregunta se responde a sí misma.

Si L1 fuera más grande que L2 (combinado), entonces no habría necesidad de caché L2.

¿Por qué almacenaría sus cosas en una unidad de cinta si puede almacenarlas todas en el disco duro?


La respuesta de @Aater explica algunos de los conceptos básicos . Agregaré algunos detalles más + un ejemplo de la organización de caché real en Intel Haswell y AMD Piledriver, con latencias y otras propiedades, no solo de tamaño.

Para algunos detalles sobre IvyBridge, vea mi respuesta en "¿Cómo puede ser tan rápido el caché?" , con un análisis de la latencia general de uso de carga, incluido el tiempo de cálculo de la dirección y los anchos de los buses de datos entre los diferentes niveles de caché.

L1 debe ser muy rápido (latencia y rendimiento), incluso si eso significa una tasa de aciertos limitada . L1d también debe admitir tiendas de un solo byte en casi todas las arquitecturas y (en algunos diseños) accesos no alineados. Esto dificulta el uso de ECC (códigos de corrección de errores) para proteger los datos, y de hecho, algunos diseños L1d (Intel) solo usan paridad, con un mejor ECC solo en los niveles externos de caché (L2 / L3) donde se puede hacer el ECC en trozos más grandes para una menor sobrecarga.

Es imposible diseñar un solo nivel de caché que pueda proporcionar la baja latencia de solicitud promedio (promediada en todos los accesos y fallos) de un caché moderno de múltiples niveles . Dado que los sistemas modernos tienen múltiples núcleos muy hambrientos que comparten una conexión a la misma DRAM de latencia relativamente alta, esto es esencial.

Cada núcleo necesita su propio L1 privado para la velocidad, pero al menos el último nivel de caché suele compartirse, por lo que un programa de múltiples subprocesos que lee los mismos datos de varios subprocesos no tiene que ir a la DRAM en cada núcleo. (Y para actuar como respaldo para los datos escritos por un núcleo y leídos por otro). Esto requiere al menos dos niveles de caché para un sistema de múltiples núcleos sano, y es parte de la motivación para más de 2 niveles en los diseños actuales. Las modernas CPU x86 de múltiples núcleos tienen un caché rápido de 2 niveles en cada núcleo y un caché más grande y más lento compartido por todos los núcleos.

La tasa de aciertos de L1 sigue siendo muy importante, por lo que los cachés de L1 no son tan pequeños / simples / rápidos como podrían ser, porque eso reduciría las tasas de aciertos. Lograr el mismo rendimiento general requeriría, por lo tanto, niveles más altos de caché para ser más rápido. Si los niveles más altos manejan más tráfico, su latencia es un componente más grande de la latencia promedio, y se producen cuellos de botella en su rendimiento con mayor frecuencia (o necesitan un rendimiento más alto).

El alto rendimiento a menudo significa poder manejar múltiples lecturas y escrituras en cada ciclo, es decir, en múltiples puertos. Esto requiere más área y potencia para la misma capacidad que un caché de menor rendimiento, por lo que esa es otra razón para que L1 se quede pequeño.

L1 también usa trucos de velocidad que no funcionarían si fueran más grandes . es decir, la mayoría de los diseños utilizan L1 virtualmente indexado y etiquetado físicamente (VIPT) , pero todos los bits de índice provienen de debajo del desplazamiento de la página, por lo que se comportan como PIPT (porque los bits bajos de una dirección virtual son los mismos que en la dirección física) . Esto evita los sinónimos / homónimos (los hits falsos o los mismos datos están dos veces en el caché, y ven la respuesta detallada de Paul Clayton en la pregunta vinculada), pero aún así, parte de la verificación de fallos / fallos ocurre en paralelo con la búsqueda de TLB. Un caché VIVT no tiene que esperar al TLB, pero debe ser invalidado en cada cambio en las tablas de páginas.

En x86 (que utiliza páginas de memoria virtual 4kiB), los cachés asociativos L1 32kiB de 8 vías son comunes en los diseños modernos. Las 8 etiquetas se pueden recuperar en función de los 12 bits bajos de la dirección virtual, porque esos bits son los mismos en las direcciones físicas y virtuales (están debajo del desplazamiento de la página para las páginas de 4kiB). Este hackeo de velocidad para cachés L1 solo funciona si son lo suficientemente pequeños y asociativos como para que el índice no dependa del resultado de TLB. 32 kB / 64 B líneas / asociatividad de 8 vías = 64 (2 ^ 6) series. Así que los 6 bits más bajos de una dirección seleccionan bytes dentro de una línea, y los 6 bits siguientes indexan un conjunto de 8 etiquetas. Este conjunto de 8 etiquetas se obtiene en paralelo con la búsqueda de TLB, por lo que las etiquetas se pueden comparar en paralelo con los bits de selección de página física del resultado de TLB para determinar cuál (si existe) de las 8 formas de caché retienen los datos. .

Hacer un caché L1 más grande significaría que tenía que esperar el resultado de la TLB antes de que pudiera comenzar a buscar etiquetas y cargarlas en los comparadores paralelos, o tendría que aumentar la asociatividad para mantener log2 (conjuntos) + log2 (tamaño de línea) <= 12. (Más asociatividad significa más formas por conjunto => menos conjuntos totales = menos bits de índice). Entonces, por ejemplo, un caché de 64 kB debería ser asociativo de 16 vías: aún 64 conjuntos, pero cada conjunto tiene el doble de formas. Esto hace que aumentar el tamaño de L1 más allá del tamaño actual sea prohibitivo en términos de potencia, y probablemente incluso de latencia.

Gastar más de su presupuesto de energía en la lógica de la memoria caché L1D dejaría menos energía disponible para la ejecución fuera de orden, la decodificación y, por supuesto, la memoria caché L2 y así sucesivamente . Hacer que todo el núcleo se ejecute a 4 GHz y mantenga aproximadamente 4 instrucciones por reloj (en código ILP alto) sin fusión requiere un diseño equilibrado. Vea este artículo: Microprocesadores modernos: ¡Una guía de 90 minutos! .

Cuanto más grande es una memoria caché, más se pierde al vaciarla, por lo que una memoria caché VIVT L1 grande sería peor que la actual PIPT de tipo VIPT que funciona como. Y un L1D más grande pero con una latencia más alta probablemente también sería peor.

De acuerdo con @PaulClayton , las memorias caché L1 a menudo recuperan todos los datos en un conjunto en paralelo con las etiquetas, por lo que están listas para ser seleccionadas una vez que se detecte la etiqueta correcta. El costo de energía de hacer esto se escala con la asociatividad, por lo que un gran L1 altamente asociativo sería realmente malo para el uso de energía así como para el área de troquel (y la latencia) . (En comparación con L2 y L3, no sería una gran área, pero la proximidad física es importante para la latencia. Los retrasos en la velocidad de la luz son importantes cuando los ciclos de reloj son 1/4 de un nanosegundo).

Los cachés más lentos (como L3) se pueden ejecutar a una velocidad de reloj / voltaje más baja para producir menos calor. Incluso pueden usar diferentes disposiciones de transistores para cada celda de almacenamiento, para hacer que la memoria esté más optimizada para la potencia que para la alta velocidad.

Hay muchas razones relacionadas con el uso de la energía para cachés multinivel. La energía / calor es una de las restricciones más importantes en el diseño moderno de la CPU, porque es difícil enfriar un pequeño chip. Todo es un intercambio entre velocidad y potencia (y / o área de matriz). Además, muchas CPU funcionan con baterías o se encuentran en centros de datos que necesitan refrigeración adicional.

L1 casi siempre se divide en instrucciones separadas y cachés de datos. En lugar de un puerto de lectura adicional en un L1 unificado para admitir la obtención de códigos, podemos tener un caché L1I separado vinculado a un I-TLB separado. (Las CPU modernas a menudo tienen un L2-TLB, que es un segundo nivel de caché para las traducciones que comparte el L1 I-TLB y el D-TLB, NO un TLB usado por el caché L2 regular). Esto nos da un total de 64 kB de caché L1, particionado estáticamente en cachés de código y datos, por mucho más barato (y probablemente menor latencia) que un caché unificado de 64k L1 monstruo con el mismo rendimiento total. Dado que generalmente hay muy poca superposición entre el código y los datos, esta es una gran victoria.

L1I puede colocarse físicamente cerca de la lógica de obtención de código, mientras que L1D puede estar físicamente cerca de las unidades de carga / almacenamiento. Los retrasos en la línea de transmisión de la velocidad de la luz son un gran problema cuando un ciclo de reloj dura solo 1/3 de un nanosegundo. El enrutamiento del cableado también es importante: por ejemplo, Intel Broadwell tiene 13 capas de cobre por encima del silicio .

Split L1 ayuda mucho con la velocidad, pero L2 unificada es la mejor opción. Algunas cargas de trabajo tienen un código muy pequeño pero tocan muchos datos. Tiene sentido que las memorias caché de nivel superior se unifiquen para adaptarse a diferentes cargas de trabajo, en lugar de partición estática en código frente a datos. (por ejemplo, casi todo L2 almacenará datos en caché, no código, mientras se ejecuta una gran matriz multiplicada, en lugar de tener un montón de código activo al ejecutar un programa C ++ inflado, o incluso una implementación eficiente de un algoritmo complicado (por ejemplo, ejecutar gcc) ). El código se puede copiar como datos, no siempre solo se carga desde el disco a la memoria con DMA.

Los cachés también necesitan lógica para rastrear fallas pendientes (ya que la ejecución fuera de orden significa que las nuevas solicitudes pueden seguir generándose antes de que se resuelva la primera falla). Tener muchos errores pendientes significa que se superpone a la latencia de los errores, logrando un mayor rendimiento. Duplicar la lógica y / o la partición estática entre el código y los datos en L2 no sería bueno.

Los cachés más grandes de menor tráfico también son un buen lugar para poner la lógica de búsqueda previa. La búsqueda previa de hardware permite un buen rendimiento para cosas como el bucle sobre una matriz sin que cada pieza de código necesite instrucciones de búsqueda previa de software. (La captación previa de SW fue importante por un tiempo, pero las buscadoras previas de HW son más inteligentes de lo que solían ser, por lo que los consejos de Ulrich Drepper son excelentes. Lo que todo programador debería saber sobre la memoria está desactualizado en muchos casos de uso).

Las memorias caché de bajo nivel de tráfico de alto nivel pueden permitirse la latencia para hacer cosas inteligentes como usar una política de reemplazo adaptable en lugar de la LRU habitual. Intel IvyBridge y las CPU posteriores hacen esto , para resistir los patrones de acceso que no obtienen resultados de caché para un conjunto de trabajo un poco demasiado grande para caber en el caché. (p. ej., hacer un bucle sobre algunos datos en la misma dirección dos veces significa que probablemente se desaloje justo antes de que se reutilice).

Un ejemplo real: Intel Haswell . Fuentes: análisis de microarquitectura de David Kanter y resultados de las pruebas de Agner Fog (microarch pdf) . Consulte también los manuales de optimización de Intel (enlaces en la etiqueta wiki x86 ).

Además, escribí una respuesta por separado en: ¿Qué técnica de mapeo de caché se usa en el procesador Intel Core i7?

Los diseños modernos de Intel utilizan un gran caché L3 inclusivo compartido por todos los núcleos como respaldo para el tráfico de coherencia de caché . Se distribuye físicamente entre los núcleos, con 2048 conjuntos * 16 vías (2MiB) por núcleo (con una política de reemplazo adaptable en IvyBridge y versiones posteriores ).

Los niveles más bajos de caché son por núcleo.

  • L1 : por núcleo 32kiB cada instrucción y datos (división), asociativo de 8 vías. Latencia = 4 ciclos . Al menos 2 puertos de lectura + 1 puerto de escritura. ( Quizás incluso más puertos para manejar el tráfico entre L1 y L2 , o tal vez la recepción de una línea de caché de L2 esté en conflicto con el retiro de una tienda). Puede rastrear 10 fallas de caché pendientes (10 buffers de relleno).
  • L2 : 256kB por núcleo unificado, asociativo de 8 vías. Latencia = 11 o 12 ciclos . Ancho de banda de lectura: 64 bytes / ciclo. La lógica de prefetching principal precede a L2. Puede rastrear 16 fallos pendientes. Puede suministrar 64B por ciclo al L1I o L1D. El puerto actual cuenta desconocido.
  • L3 : unificado, compartido (por todos los núcleos) 8MiB (para un i7 de cuatro núcleos). Inclusivo (de todas las caches L2 y L1 por núcleo). Asociado de 12 o 16 vías. Latencia = 34 ciclos . Actúa como respaldo para la coherencia de caché, por lo que los datos compartidos modificados no tienen que salir a la memoria principal y viceversa.

Otro ejemplo real: AMD Piledriver : (p. Ej., Las CPUs Opteron y FX de escritorio). El tamaño de la línea de caché sigue siendo 64B, como Intel y AMD han usado durante varios años. Texto copiado principalmente del pdf de microargar de Agner Fog, con información adicional de algunas diapositivas que encontré , y más detalles sobre el caché de escritura combinada L1 + 4k en el blog de Agner , con un comentario de que solo L1 es WT, no L2 .

  • L1I : 64 kB, de 2 vías, compartido entre un par de núcleos (la versión de SMD de AMD tiene una partición más estática que Hyperthreading, y llaman a cada uno un núcleo. Cada par comparte una unidad de vector / FPU y otros recursos de canalización.)
  • L1D : 16 kB, 4 vías, por núcleo. Latencia = 3-4 c . (Tenga en cuenta que los 12 bits por debajo del desplazamiento de la página aún se utilizan para el índice, por lo que el truco habitual de VIPT funciona). (Rendimiento: dos operaciones por reloj, de las cuales una es una tienda). Política = Escritura directa , con un caché de combinación de escritura 4k.
  • L2 : 2 MB, 16 vías, compartido entre dos núcleos. Latencia = 20 relojes . Lea el rendimiento 1 por 4 horas. Escriba el rendimiento 1 por 12 horas.
  • L3 : 0 - 8 MB, 64 vías, compartido entre todos los núcleos. Latencia = 87 reloj . Leer el rendimiento 1 por 15 horas. Escriba el rendimiento 1 por 21 horas

Agner Fog informa que con ambos núcleos de un par activo, el rendimiento de L1 es menor que cuando la otra mitad del par está inactiva. No se sabe qué está pasando, ya que se supone que los cachés L1 están separados para cada núcleo.