¿Cómo escriben las CPU Intel Xeon en la memoria?


Estoy tratando de decidir entre dos algoritmos. Uno escribe 8 bytes (dos palabras alineadas de 4 bytes) en 2 líneas de caché, el otro escribe 3 líneas de caché completas.

Si la CPU escribe solo los 8 bytes cambiados en la memoria, entonces el primer algoritmo usa mucho menos ancho de banda de memoria: 8 bytes vs 192 bytes. Si la CPU escribe líneas de caché completas, entonces la diferencia entre 128 y 192 bytes es menos llamativa.

Entonces, ¿cómo escribe una CPU Intel Xeon en la memoria? Te sorprenderías de lo difícil que es es encontrar una respuesta en Google a algo que debería ser bien conocido.

Según lo entiendo, las escrituras van al buffer de la tienda, y luego a la caché. Es posible que solo se escriban en la memoria cuando la línea de caché sucia es desalojada de la caché, pero Intel rastrea qué partes de la línea de caché están sucias, o simplemente volcan toda la cosa? Dudo que rastreen las cosas por debajo de la granularidad de la línea de caché. También me sorprendería mucho si algo va a la memoria antes de la línea de caché es desalojado.

Author: Peter Cordes, 2015-07-25

2 answers

La localidad importa incluso para la propia DRAM, incluso descontando el almacenamiento en caché. Una escritura en ráfaga de 64B bytes contiguos para una línea de caché sucia es mucho más rápida que 16 escrituras de 4B a 16 direcciones diferentes. O para decirlo de otra manera, escribir una línea de caché completa no es mucho más lento que escribir solo unos pocos bytes cambiados en una línea de caché.

Lo que Todo Programador Debe Saber Sobre la Memoria , por Ulrich Drepper, explica muchas cosas sobre cómo evitar los cuellos de botella de la memoria cuando programación. Él incluye algunos detalles de DRAM dirección. Los controladores DRAM tienen que seleccionar una fila y, a continuación, seleccionar una columna. Acceder a otra página de memoria virtual también puede causar un error de TLB.

DRAM tiene un comando burst-transfer para transferir un fragmento secuencial de datos. (Obviamente diseñado para el beneficio de las CPU escribiendo líneas de caché). El sistema de memoria en las computadoras modernas está optimizado para el patrón de uso de escribir líneas de caché completas, porque eso es casi siempre suceder.

Las líneas de caché son la unidad en la que las CPU rastrean dirty-or-not. Sería posible rastrear la suciedad con un tamaño de línea más pequeño que las líneas de caché presentes o no, pero eso requeriría transistores adicionales y no vale la pena. Los múltiples niveles de caché están configurados para transferir líneas de caché completas, por lo que pueden ser lo más rápidos posible cuando se necesita leer una línea de caché completa.

Existen las llamadas lecturas/escrituras no temporales (movnti/movntdqa) que omiten la caché. Estos son para usar con datos que no se volverán a tocar hasta que hayan sido desalojados de la caché de todos modos (de ahí los no temporales). Son una mala idea para los datos que podrían beneficiarse del almacenamiento en caché, pero le permitiría escribir 4 bytes en la memoria, en lugar de una línea de caché completa. Dependiendo del MTRR para ese rango de memoria, la escritura podría o no estar sujeta a la combinación de escritura. (Esto es relevante para regiones de e/s mapeadas en memoria, donde dos escrituras 4B adyacentes no son lo mismo que una 8B escribir.)

El algoritmo que solo toca dos líneas de caché ciertamente tiene la ventaja en esa puntuación, a menos que se necesite mucho más cálculo, o especialmente ramificación, para averiguar qué memoria escribir. Tal vez hacer una pregunta diferente si quieres ayuda para decidir. (ver los enlaces en https://stackoverflow.com/tags/x86/info , las guías de esp Agner Fog, para obtener información que le ayudará a decidir por sí mismo.)

Ver la respuesta de Cornstalks para advertencias sobre los peligros de tener múltiples subprocesos en diferentes CPU que tocan la misma memoria. Esto puede conducir a ralentizaciones más grandes que solo escrituras adicionales para un programa de un solo subproceso.

 17
Author: Peter Cordes,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:17:49

Para que la CPU escriba solo los bytes sucios en la memoria, necesitaría almacenar un bit sucio para cada byte en la caché. Eso es inviable y no se hace en CPU modernas (que yo sepa). Las CPU solo tienen un bit sucio para una línea de caché. Escribir en cualquier byte en la línea de caché hace que toda la línea se marque como sucia.

Cuando llega el momento de limpiar la línea de caché sucia, toda la línea debe escribirse, porque la CPU no tiene idea de qué byte(s) cambiar.

Esto se puede ver en las políticas de invalidación de caché en las que escribir en una línea de caché en un núcleo puede invalidar la línea de caché en un núcleo diferente (porque las dos líneas de caché se asignan a la misma dirección), incluso si el primer núcleo está utilizando la mitad baja de la línea de caché y el segundo núcleo está utilizando la mitad alta de la línea de caché. Es decir, si core 1 escribe en byte N, y core 2 está usando byte N+1, entonces core 2 todavía tiene que actualizar su línea de caché a pesar de que usted y yo sabemos que no es necesario.

 8
Author: Cornstalks,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-07-25 21:15:13