¿Qué técnica de mapeo de caché se usa en el procesador intel core i7?

Aprendí sobre diferentes técnicas de mapeo de caché, como el mapeo directo, el mapeo asociado y la técnica de mapeo asociativo de conjuntos, y también aprendí las ventajas y desventajas. Pero tengo curiosidad por saber qué se usa en el procesador intel core i7 o AMD hoy en día. Y cómo se evolucionan las técnicas. ¿Y qué cosas hay que mejorar?

Los cachés de mapa directo básicamente nunca se usan en las CPU modernas de alto rendimiento . Los ahorros de energía se ven compensados ​​por la gran ventaja en la tasa de aciertos para una memoria caché asociativa de conjunto del mismo tamaño, con solo un poco más de complejidad en la lógica de control. Los presupuestos de transistores son muy grandes actualmente.

Es muy común que el software tenga al menos un par de matrices que son un múltiplo de 4k separadas entre sí, lo que crearía fallas de conflicto en un caché de mapeo directo. (El código de ajuste con más de un par de matrices puede implicar un sesgo para reducir las fallas de conflicto, si un ciclo necesita iterar a través de todas ellas a la vez)

Las CPU modernas son tan rápidas que la latencia de DRAM supera los 200 ciclos de reloj centrales, que es demasiado grande incluso para que las poderosas CPU de ejecución fuera de servicio se oculten muy bien en una falla de caché.


Las memorias caché de niveles múltiples son esenciales (y se utilizan todas las CPU de alto rendimiento) para proporcionar baja latencia (~ 4 ciclos) / alto rendimiento para los datos más populares (por ejemplo, hasta 2 cargas y 1 tienda por reloj , con 128, 256 o incluso la ruta de 512 bits entre la memoria caché L1D y las unidades de ejecución de carga / almacenamiento de vectores), sin dejar de ser lo suficientemente grande como para almacenar en caché un conjunto de trabajo de tamaño razonable. Es físicamente imposible construir un caché muy grande / muy rápido / altamente asociativo que funcione tan bien como los cachés de niveles múltiples actuales para cargas de trabajo típicas; Las demoras en la velocidad de la luz cuando los datos tienen que viajar físicamente lejos son un problema. El costo de la energía sería prohibitivo también. (De hecho, la densidad de potencia / potencia es un factor limitante importante para las CPU modernas, consulte Modern Microprocessors: A 90-Minute Guide! ).

Todos los niveles de caché (excepto el caché uop) están físicamente indexados / etiquetados físicamente en todas las CPU x86 que conozco. Las memorias caché L1D en la mayoría de los diseños toman sus bits de índice de debajo del desplazamiento de página, y por lo tanto también son VIPT permitiendo que la búsqueda de TLB ocurra en paralelo con la búsqueda de tags, pero sin ningún problema de aliasing. Por lo tanto, no es necesario enjuagar los cachés en los conmutadores de contexto ni nada. (Consulte esta respuesta para obtener más información acerca de los cachés de niveles múltiples en general y el truco de velocidad VIPT, y algunos parámetros de caché de algunas CPU x86 reales).


Los cachés L1D / L1I y L2 privados (por núcleo) son cachés asociativos conjuntos tradicionales , a menudo de 8 o 4 direcciones para cachés pequeños / rápidos. El tamaño de la línea de caché es de 64 bytes en todas las CPU modernas x86. Los cachés de datos son write-back. (Excepto en AMD Bulldozer-family, donde L1D es write-through con un pequeño búfer de combinación de escritura 4kiB).

http://www.7-cpu.com/ tiene buenos números de organización / latencia de caché, y ancho de banda, y números de organización / rendimiento de TLB, para varias microarchitectures, incluyendo muchos x86, como Haswell .

La memoria caché descodificada “L0” en Intel Sandybridge-family es set-associative y virtualmente tratada . Hasta 3 bloques de hasta 6 uops pueden almacenar en caché los resultados de deencoding de las instrucciones en un bloque de código de máquina de 32 bytes. Relacionado: alineación de bifurcación para bucles que implican instrucciones microcodificadas en CPU de la familia Intel SnB . (Una memoria caché uop es un gran avance para x86: las instrucciones x86 son de longitud variable y difíciles de decodificar rápido / en paralelo, por lo que el almacenamiento en caché de los resultados de deencoding interna y el código de máquina (L1I $) tienen ventajas significativas de potencia y rendimiento. aún se necesitan decodificadores, porque la memoria caché uop no es grande, es más efectiva en bucles (incluyendo bucles medianos a grandes). Esto evita el error Pentium4 (o la limitación basada en el tamaño del transitorio en ese momento) de tener decodificadores débiles y confiar en el caché de seguimiento).


Los modernos Intel (y AMD, supongo) L3 aka LLC aka cachés de último nivel usan una función de indexación que no es solo un rango de bits de direcciones . Es una función hash que distribuye mejor las cosas para reducir las colisiones de zancadas fijas. Según Intel, mi memoria caché debe ser de 24 vías asociativa, aunque es de 12 vías, ¿cómo es eso? .


Desde Nehalem en adelante , Intel ha utilizado un gran caché L3 compartido inclusivo , que filtra el tráfico de coherencia entre los núcleos . es decir, cuando un núcleo lee datos que están en estado Modificado en L1d de otro núcleo, las tags L3 dicen qué núcleo, por lo que una RFO (Read For Ownership) puede enviarse solo a ese núcleo, en lugar de transmitir. ¿Cómo se organizan los cachés modernos de Intel CPU L3? . La propiedad inclusivity es importante, porque significa que ninguna caché privada L2 o L1 puede tener una copia de una línea de caché sin que L3 lo sepa. Si está en estado Exclusivo o Modificado en un caché privado, L3 tendrá datos no válidos para esa línea, pero las tags seguirán indicando qué núcleo puede tener una copia. Los núcleos que definitivamente no tienen una copia no necesitan que se les envíe un mensaje al respecto, lo que ahorra energía y ancho de banda a través de los enlaces internos entre los núcleos y L3. Consulte Por qué On-Chip Cache Coherence está aquí para quedarse para obtener más detalles sobre la coherencia del caché en el chip en Intel “i7” (es decir, Nehalem y Sandybridge-family, que son architectures diferentes pero utilizan la misma jerarquía de caché).

Core2Duo tenía un caché compartido de último nivel (L2), pero tardaba en generar solicitudes RFO (Read-For-Ownership) en errores L2. Por lo tanto, el ancho de banda entre núcleos con un pequeño búfer que se ajusta en L1d es tan lento como con un búfer grande que no cabe en L2 (es decir, la velocidad de DRAM). Hay un rango rápido de tamaños cuando el buffer se ajusta en L2 pero no en L1d, porque el núcleo de escritura expulsa sus propios datos a L2 donde las cargas del otro núcleo pueden golpear sin generar una solicitud RFO. (Consulte la Figura 3.27: Ancho de banda del Core 2 con 2 hilos en “Lo que todo progtwigdor debería saber sobre la memoria” de Ulrich Drepper. ( Versión completa aquí ).


Skylake-AVX512 tiene un L2 por núcleo más grande (1MiB en lugar de 256k), y rebanadas más pequeñas de L3 (LLC) por núcleo. Ya no es inclusivo . Utiliza una red de malla en lugar de un bus de anillo para conectar núcleos entre sí. Vea este artículo de AnandTech (pero tiene algunas inexactitudes en los detalles microarquitectónicos en otras páginas, vea el comentario que dejé ).

Desde la descripción técnica general de la familia escalable del procesador Intel® Xeon®

Debido a la naturaleza no inclusiva de LLC , la ausencia de una línea de caché en LLC no indica que la línea no esté presente en cachés privados de ninguno de los núcleos. Por lo tanto, se usa un filtro snoop para realizar un seguimiento de la ubicación de las líneas de caché en el L1 o MLC de los núcleos cuando no está asignado en la LLC. En las CPU de la generación anterior, la propia LLC compartida se encargó de esta tarea.

Este “filtro snoop” solo es útil si no puede tener falsos negativos. Está bien enviar un invalidado o RFO ( MESI ) a un núcleo que no tiene una copia de una línea. No está bien dejar que un núcleo conserve una copia de una línea cuando otro núcleo está solicitando acceso exclusivo a ella. Por lo tanto, puede ser un rastreador con etiqueta incluida que sepa qué núcleos pueden tener copias de qué línea, pero que no almacena datos en caché.

O tal vez el filtro snoop todavía puede ser útil sin ser estrictamente inclusivo de todas las tags L2 / L1. No soy un experto en protocolos snoop multi-core / multi-socket. Creo que el mismo filtro de snoop también puede ayudar a filtrar las solicitudes de búsqueda entre sockets. (En Broadwell y antes, solo Xeons de cuádruple zócalo y superior tienen un filtro de snoop para tráfico entre núcleos, Broadwell Xeon de doble zócalo y versiones anteriores no filtran las solicitudes de snoop entre los dos zócalos ).


AMD Ryzen utiliza cachés L3 separados para clusters de núcleos , por lo que los datos compartidos en muchos núcleos deben duplicarse en L3 para cada clúster. También es importante destacar que las escrituras desde un núcleo en un clúster tardan más tiempo en ser visibles para un núcleo en otro clúster, y las solicitudes de coherencia deben pasar por una interconexión entre clusters. (Similar a entre sockets en un sistema Intel de varios sockets, donde cada paquete de CPU tiene su propio L3).

Así que esto nos da NUCA (Acceso a caché no uniforme), análogo al NUMA habitual (acceso a memoria no uniforme) que se obtiene en un sistema multi-socket donde cada procesador tiene un controlador de memoria incorporado, y el acceso a la memoria local es más rápido que acceder a la memoria conectada a otro socket.


Los sistemas recientes de múltiples sockets de Intel tienen modos de snoop configurables, por lo que en teoría puede ajustar el mecanismo NUMA para que funcione mejor para la carga de trabajo que está ejecutando. Consulte la página de Intel sobre Broadwell-Xeon para obtener una tabla + descripción de los modos de búsqueda disponibles.


Otro avance / evolución es una política de reemplazo adaptativo en L3 en IvyBridge y posterior . Esto puede reducir la contaminación cuando algunos datos tienen una localidad temporal, pero otras partes del conjunto de trabajo son mucho más grandes. (es decir, hacer un bucle sobre una matriz gigante con un reemplazo LRU estándar desalojará todo, dejando la caché L3 solo almacenando en caché los datos de la matriz que no volverán a tocarse pronto. La sustitución adaptativa intenta mitigar ese problema).


Otras lecturas:

  • ¿Qué debería saber todo progtwigdor sobre la memoria?
  • ¿Por qué Skylake es mucho mejor que Broadwell-E para el rendimiento de la memoria de un único subproceso? ? (El ancho de banda de la memoria de un solo subproceso en las CPU Xeon de muchos núcleos está limitado por max_concurrency / latency, no por el ancho de banda de DRAM).
  • http://users.atw.hu/instlatx64/ para resultados de tiempo de rendimiento de memoria
  • http://www.7-cpu.com/ para la organización de caché / TLB y los números de latencia.
  • http://agner.org/optimize/ para detalles de microarchitecture (principalmente sobre la canalización de ejecución, no sobre la memoria), y guías de optimización asm / C ++.
  • El wiki de la etiqueta x86 de Stack Overflow tiene una sección de rendimiento, con enlaces a esos y más.
    Intereting Posts