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

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

Hay diferentes razones para eso.

L2 existe en el sistema para agilizar el caso en el que falta un caché L1. Si el tamaño de L1 era igual o mayor que el tamaño de L2, entonces L2 no podría acomodar más líneas de caché que L1, y no podría lidiar con fallas de caché L1. Desde la perspectiva del diseño / costo, la memoria caché L1 está ligada al procesador y es más rápida que L2. La idea de las memorias caché es que acelere el acceso al hardware más lento agregando hardware intermedio que es más eficiente (y costoso) que el hardware más lento y, a la vez, más económico que el hardware más rápido que tiene. Incluso si decidiera duplicar la caché L1, también incrementaría L2, para acelerar los errores L1-caché.

Entonces, ¿por qué hay caché L2 en absoluto? Bueno, la memoria caché L1 suele ser más eficiente y costosa de construir, y está ligada a un único núcleo. Esto significa que boost el tamaño de 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. L2 generalmente es compartido por diferentes núcleos: dependiendo de la architecture, puede compartirse en un par o en todos los núcleos del procesador, por lo que el costo de boost L2 sería menor, incluso si el precio de L1 y L2 fuera el mismo, lo cual no lo es.

L1 está muy estrechamente acoplado al núcleo de la CPU, y se accede a él en cada acceso a la memoria (muy frecuente). Por lo tanto, necesita devolver los datos realmente rápido (generalmente dentro del ciclo del reloj). La latencia y el rendimiento (ancho de banda) son críticos para el rendimiento de la memoria caché de datos L1. (por ejemplo, latencia de cuatro ciclos, y admitir dos lecturas y una escritura por núcleo de la CPU en cada ciclo de reloj). Necesita muchos puertos de lectura / escritura para admitir este alto ancho de banda de acceso. Construir un caché grande 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 accedió a L2 solo en fallas L1, por lo que los accesos son menos frecuentes (generalmente 1/20 de L1). Por lo tanto, L2 puede tener una mayor latencia (por ejemplo, de 10 a 20 ciclos) y tener menos puertos. Esto permite a los diseñadores hacerlo más grande.


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

Si eliminamos L2, las fallas de L1 tendrán 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 el 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 éxitos más rápido) y L2 como un filtro de ancho de banda, ya que reduce el uso de ancho de banda de 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 actuales, hay un caché L3 compartido entre todos los núcleos, mientras que cada núcleo tiene su propia L1 privada y quizás L2. En estos chips, el caché compartido de último nivel (L3) cumple la función de filtro de ancho de banda de memoria. L2 juega 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 utilizar una interconexión de menor ancho de banda como un anillo, y un L3 de un solo puerto lento, lo que les permite boost la L3.

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

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

Para obtener más información sobre IvyBridge, consulte mi respuesta sobre “¿Cómo puede la memoria caché ser tan rápida?” , con alguna discusión sobre la latencia general del uso de la carga, incluido el tiempo de cálculo de la dirección y el ancho de los buses de datos entre los diferentes niveles de caché.


L1 necesita ser muy rápido (latencia y rendimiento), incluso si eso significa una tasa de aciertos limitada . L1d también necesita admitir almacenes de un solo byte en casi todas las architectures, y (en algunos diseños) accesos desalineados. Esto hace que sea difícil usar 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 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 latencia de solicitud promedio baja (promediada sobre todos los aciertos y fallos) de un caché moderno de varios niveles . Como los sistemas modernos tienen múltiples núcleos muy hambrientos que comparten una conexión con 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é generalmente se comparte, por lo que un progtwig de subprocesos múltiples que lee los mismos datos de varios subprocesos no tiene que ir a DRAM en cada núcleo. (Y para actuar como un respaldo para datos escritos por un núcleo y leídos por otro). Esto requiere al menos dos niveles de caché para un sistema cuerdo multi-núcleo, y es parte de la motivación para más de 2 niveles en los diseños actuales. Las CPU x86 multinúcleo modernas tienen una memoria caché rápida de 2 niveles en cada núcleo y una caché lenta más grande compartida por todos los núcleos.

La tasa de aciertos de L1 sigue siendo muy importante, por lo que los cachés 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, por lo tanto, requeriría niveles más altos de caché para ser más rápidos. Si los niveles más altos manejan más tráfico, su latencia es un componente mayor de la latencia promedio, y obstaculizan su rendimiento más a menudo (o necesitan un mayor rendimiento).

El alto rendimiento a menudo significa ser capaz de manejar múltiples lecturas y escrituras en cada ciclo, es decir, 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 fuera más grande . es decir, la mayoría de los diseños utilizan L1 prácticamente indexado, físicamente etiquetado (VIPT) , pero con todos los bits de índice por debajo del desplazamiento de 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 sinónimos / homónimos (resultados falsos o la misma información en la memoria caché dos veces, y ver la respuesta detallada de Paul Clayton en la pregunta vinculada), pero aún permite que parte del control de coincidencia ocurra en paralelo con la búsqueda de TLB. Un caché VIVT no tiene que esperar al TLB, pero debe invalidarse en cada cambio en las tablas de página.

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

Hacer un caché L1 más grande significaría que tuvo que esperar el resultado de TLB antes de que incluso pudiera comenzar a buscar tags y cargarlas en los comparadores paralelos, o tendría que boost en asociatividad para mantener log2 (sets) + log2 (line_size) <= 12. (Más asociatividad significa más formas por conjunto => menos conjuntos totales = menos bits de índice). Entonces, por ejemplo, un caché de 64kiB necesitaría ser de 16 vías asociativo: todavía 64 conjuntos, pero cada conjunto tiene el doble de formas. Esto hace que boost el tamaño de L1 más allá del tamaño actual sea prohibitivamente caro en términos de potencia, y probablemente incluso de latencia.

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

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

Según @PaulClayton , los cachés L1 a menudo captan todos los datos en un conjunto en paralelo con las tags, por lo que están listos para ser seleccionados una vez que se detecta la etiqueta correcta. El costo de energía de hacer esto se escala con la asociatividad, por lo que una gran L1 altamente asociativa sería realmente mala para el uso de energía, así como para el área de la matriz (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 de propagación de la velocidad de la luz son importantes cuando los ciclos del reloj son 1/4 de un nanosegundo).

Las memorias caché más lentas (como L3) pueden funcionar a una tensión / velocidad de reloj 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 muchos motivos relacionados con el uso de la energía para cachés de varios niveles. La potencia / calor es una de las limitaciones más importantes en el diseño de la CPU moderna, porque enfriar un chip pequeño es difícil. Todo es una compensación entre velocidad y potencia (y / o área muerta). 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 cachés de datos e instrucciones separadas. En lugar de un puerto de lectura adicional en un L1 unificado para admitir la captura de código, 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 comparten L1 I-TLB y D-TLB, NO un TLB utilizado por el caché L2 normal). Esto nos da un total de 64 kB de caché L1, estáticamente dividido en cachés de datos y códigos, por mucho más barato (y probablemente menor latencia) que un caché unificado de 64 k L1 con el mismo rendimiento total. Como generalmente hay muy poca superposición entre el código y los datos, esta es una gran victoria.

L1I se puede ubicar físicamente cerca de la lógica de búsqueda de códigos, 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. Enrutar el cableado también es un gran problema: por ejemplo, Intel Broadwell tiene 13 capas de cobre por encima del silicio .

Split L1 ayuda mucho con la velocidad, pero unificado L2 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 ejecuta una multiplicación de matriz grande, teniendo mucho código caliente mientras ejecuta un progtwig inflado de C ++, o incluso una implementación eficiente de un algoritmo complicado (por ejemplo, ejecutando gcc) ) El código se puede copiar como datos, no siempre solo se carga desde el disco en la memoria con DMA.


Las cachés también necesitan lógica para rastrear las 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 muchas fallas pendientes significa que se superpone la latencia de las fallas, 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.

Las memorias caché de menor tráfico también son un buen lugar para poner la lógica de precarga. La precarga de hardware permite un buen rendimiento para cosas como recorrer una matriz sin que cada fragmento de código necesite instrucciones de captación previa de software. (La captación previa de SW fue importante por un tiempo, pero los precaptores de HW son más inteligentes de lo que solían ser, por lo que los consejos en Ulrich Drepper, que de otro modo serían Lo que todo progtwigdor debería saber sobre la memoria, están desactualizados en muchos casos de uso).

Los cachés de alto nivel de bajo tráfico pueden permitirse la latencia para hacer cosas inteligentes como usar una política de reemplazo adaptativo en lugar de la LRU habitual. Intel IvyBridge y las CPU posteriores hacen esto , para resistir los patrones de acceso que no obtienen aciertos de caché para un conjunto de trabajo demasiado grande para caber en la memoria caché. (p. ej., pasar dos datos en la misma dirección dos veces significa que probablemente se desaloja justo antes de volver a usarse).


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

Además, escribí una respuesta por separado sobre: ¿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 un tope para el tráfico de coherencia de caché . Se distribuye físicamente entre los núcleos, con 2048 series * 16 vías (2MiB) por núcleo (con una política de reemplazo adaptable en IvyBridge y posterior ).

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

  • L1 : por núcleo 32kiB cada instrucción y datos (división), 8 vías asociativas. Latencia = 4 ciclos . Al menos 2 puertos de lectura + 1 puerto de escritura. ( Tal vez incluso más puertos para manejar el tráfico entre L1 y L2 , o tal vez recibir una línea de caché de L2 entra en conflicto con la retirada de una tienda.) Puede rastrear 10 errores de caché pendientes (10 búferes de relleno).
  • L2 : unificado por núcleo, 256kiB, 8 vías asociativo. Latencia = 11 o 12 ciclos . Ancho de banda de lectura: 64 bytes / ciclo. La principal lógica de captación previa se capta previamente en L2. Puede rastrear 16 fallas pendientes. Puede suministrar 64B por ciclo a L1I o L1D. El puerto real cuenta desconocido.
  • L3 : unificado, compartido (por todos los núcleos) 8MiB (para un quad-core i7). Inclusivo (de todas las cachés L2 y L1 por núcleo). 12 o 16 vías asociativas. Latencia = 34 ciclos . Actúa como un respaldo para la coherencia de la caché, por lo que los datos compartidos modificados no tienen que ir a la memoria principal y viceversa.

Otro ejemplo real: AMD Piledriver : (por ejemplo, CPU Opteron y desktop FX). El tamaño de la línea de caché sigue siendo 64B, como lo han usado Intel y AMD desde hace varios años. Texto copiado principalmente de microarch pdf 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, bidireccional, compartido entre un par de núcleos (la versión AMD de SMD tiene más particiones estáticas que Hyperthreading, y cada núcleo lo llama núcleo. Cada par comparte una unidad 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 debajo del desplazamiento de página todavía se usan para el índice, por lo que el truco VIPT habitual funciona.) (Rendimiento: dos operaciones por reloj, hasta que una de ellas sea una tienda). Policy = Write-Through , con un caché de combinación de escritura de 4k.
  • L2 : 2 MB, 16 vías, compartido entre dos núcleos. Latencia = 20 relojes . Lea el rendimiento 1 por 4 horas. Escribir el rendimiento 1 por 12 reloj.
  • L3 : 0 – 8 MB, 64 vías, compartido entre todos los núcleos. Latencia = 87 reloj . Leer rendimiento 1 por 15 reloj. Escribir el rendimiento 1 por 21 reloj

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

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

Para aquellos interesados ​​en este tipo de preguntas, mi universidad recomienda Arquitectura de Computadores: Un Enfoque Cuantitativo y Organización y Diseño de Computadoras: La Interfaz de Hardware / Software . Por supuesto, si no tiene tiempo para esto, hay una descripción general rápida disponible en Wikipedia .

Las otras respuestas aquí dan razones específicas y técnicas por las que L1 y L2 tienen el tamaño que tienen, y aunque muchas de ellas son consideraciones motivadoras para architectures particulares, en realidad no son necesarias: la presión arquitectónica subyacente conduce al aumento de caché (privado) a medida que te alejas del núcleo es bastante universal y es lo mismo que el razonamiento para cachés múltiples en primer lugar.

Los tres hechos básicos son:

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

Por lo tanto, en un nivel básico, es posible que pueda decir el doble del tamaño de la memoria caché, pero incurrir en una penalización de latencia de 1.4 en comparación con la memoria caché más pequeña.

Entonces se convierte en un problema de optimización: ¿cuántos cachés debería tener y qué tan 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 único caché bastante grande o sin memoria caché. Sin embargo, el acceso es muy poco uniforme, por lo que un caché pequeño y rápido puede capturar una gran cantidad de accesos, desproporcionados en relación con su tamaño.

Si el hecho 2 no existiera, crearías una caché L1 muy grande y muy rápida dentro de las otras restricciones de tu chip y no necesitarías ningún otro nivel de caché.

Si el hecho 3 no existiera, terminarías con una gran cantidad de “cachés” de grano fino, más rápido y pequeño en el centro, y más lento y más grande afuera, 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 se terminan con algunos niveles cuantificados de caché 2 .

Otras restricciones

Esto proporciona un marco básico para comprender el recuento de caché y las decisiones de tamaño del caché, pero también hay factores secundarios en el trabajo. Por ejemplo, Intel x86 tiene tamaños de página 4K y sus cachés L1 utilizan una architecture VIPT . VIPT significa que el tamaño de la memoria caché dividido por el número de formas no puede ser mayor que 4 KiB. Por lo tanto, un caché L1 de 8 vías tal como se utiliza en la media docena de diseños de Intel puede ser, como máximo, 4 KiB * 8 = 32 KiB. ¡Probablemente no sea una coincidencia que ese sea exactamente el tamaño de la caché L1 en esos diseños! Si no fuera por esta restricción, es muy posible que haya visto una menor asociatividad y / o cachés L1 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 la potencia, pero al mantener 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 progtwigción para las memorias caché de latencia conocida, como la mayoría de los diseños L1: y el progtwigdor fuera de orden puede enviar operaciones optimizadas que dependen de una carga de memoria en el ciclo que devolvería la caché L1. leyendo el resultado de la red de derivación. Esto reduce la contención y tal vez afeita un ciclo de latencia fuera de la ruta crítica. Esto ejerce cierta presión sobre el nivel de caché más interno para tener una latencia uniforme / predecible y probablemente da como resultado menos niveles de caché.

3 En principio, puede usar cachés VIPT sin esta restricción, pero solo requiriendo compatibilidad con el sistema operativo (por ejemplo, coloreado de página) o con otras restricciones. El arco x86 no lo ha hecho 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 la unidad de cinta si puede almacenar todo en la unidad de disco duro?