¿Hay CPU que realizan esta posible optimización de escritura de caché L1?

9

Cuando la CPU con un caché L1 escribe, lo que normalmente sucede es que (suponiendo que la línea de caché en la que está escribiendo ya está en el caché L1) el caché (además de actualizar los datos) marca esa línea de caché como sucia , y escribirá la línea con los datos actualizados en algún momento posterior.

Una posible optimización sería hacer que el caché compare los contenidos de la escritura y los contenidos anteriores del caché, y si son iguales, no marque la línea como sucia. Debido a que esto podría permitir que la memoria caché evite reescrituras en ocasiones, puedo ver cómo el fabricante de la CPU podría considerar que esto vale las puertas necesarias para hacer esta lógica.

Mi pregunta: ¿hay CPU que realicen esta optimización?

Antecedentes de por qué pregunto: estoy escribiendo un código que necesita tener accesos constantes a la memoria; es decir, alguien que puede escuchar el comportamiento del caché no debería poder deducir lo que estoy haciendo. Algunos de mis accesos son escrituras, y en la forma obvia de implementar este código, muchas de las escrituras escribirán los mismos datos que ya están allí. Necesito hacer las escrituras porque, dependiendo de los datos, los datos que estoy escribiendo pueden o no ser los mismos, y es importante realizar la misma acción independientemente. Si la CPU se optimiza al no escribir realmente una 'escritura sin cambios', eso significaría que el comportamiento de la memoria caché variará dependiendo de lo que esté haciendo, lo que subvertiría mi objetivo.

Entonces, ¿hay una CPU que intente optimizar las escrituras de esta manera?

poncho
fuente
11
Se dice que hay dos problemas verdaderamente difíciles en informática: invalidación de caché, nombrar bien las cosas y errores de uno por uno. Este es un ejemplo de por qué el primero de estos es complicado.
Mason Wheeler
@poncho usted dice que "alguien que puede escuchar el comportamiento del caché no debería poder deducir lo que estoy haciendo". Ahora, si algunas CPU implementaron esta característica de "reescritura inteligente" que no invalida la memoria caché a menos que los datos se actualicen realmente, al ir un nivel más lejos de la CPU en la jerarquía de memoria, uno podría observar el tráfico / sincronización diferencias entre escrituras reales y escrituras ficticias. ¿Es esto lo que te preocupa?
TheCodeArtist
@poncho También su pregunta real parece ser sobre la implementación de un modo mejor privilegiado / seguro que no filtre la información de uso. ¿Tal vez deberías preguntar eso? ...
TheCodeArtist
1
@TheCodeArtist: bueno, se han publicado ataques criptográficos de canal lateral en los que una rutina de cifrado podría ser atacada por otro programa que se ejecuta en un núcleo diferente de la misma CPU, haciendo que el programa de ataque monitoree la memoria caché compartida. Creo que dicho programa podría detectar potencialmente si las líneas de caché L1 estaban vacías y, por lo tanto, podría deducir información sobre el programa que me interesa, si la CPU realiza la optimización en discusión. No estoy hablando de un 'modo seguro', ya que no asumo la capacidad de modificar la CPU o el sistema operativo.
poncho
44
Incluso si esto es cierto hoy, no se garantiza que sea cierto mañana.
pjc50

Respuestas:

4

Después de horas de búsqueda, no pude encontrar una CPU que utilizara esta optimización específica. La mayoría de las optimizaciones mencionadas generalmente se relacionan con hit / miss con operaciones de lectura / escritura y acceso a datos:

(páginas 7 y) https://cseweb.ucsd.edu/classes/fa14/cse240A-a/pdf/08/CSE240A-MBT-L15-Cache.ppt.pdf

Sin embargo, eso no significa que no se pueda realizar esta optimización. En general, es posible acceder mediante programación al tamaño de una línea de caché de CPU. También es posible acceder a los valores actuales en los registros de caché, pero es algo peligroso hacerlo. Si accede a los registros incorrectos en un mal momento, podría estar manipulando los relacionados con un programa en ejecución. O podría modificar inadvertidamente el contenido de las líneas que está intentando leer.

Obteniendo el valor actual en el caché del registro

Además, todas las soluciones teóricas requieren alguna forma de implementación de software (ensamblador). Lo más cercano que he encontrado se relaciona con la arquitectura ARM, que parece permitir la manipulación de caché. Además de esto, también necesitaría saber el tamaño de una línea de caché para su CPU deseada. Podría leer cuidadosamente el contenido de la memoria caché en una ubicación secundaria en la memoria, en incrementos de tamaño de línea, y compararlo con los datos que están a punto de escribirse en los registros (o líneas de memoria caché L1, en este caso).

Leer el contenido de la memoria caché de la CPU

A partir de ahí, puede diseñar un sistema basado en software que evite reescrituras idénticas. Si bien esto está un poco simplificado, es así porque la solución debe ser aplicable a cualquier CPU que exista.

Otra posibilidad que encontré relacionada con la coherencia de caché:

Pasaje relevante de un artículo de Wikipedia sobre coherencia de acche

El punto principal que me llamó la atención, en relación con este problema, fue la descripción de Snarfing:

Es un mecanismo en el que un controlador de caché observa tanto la dirección como los datos en un intento de actualizar su propia copia de una ubicación de memoria cuando un segundo maestro modifica una ubicación en la memoria principal. Cuando se observa una operación de escritura en una ubicación de la que un caché tiene una copia, el controlador de caché actualiza su propia copia de la ubicación de memoria snarfed con los nuevos datos.

En otras palabras, posiblemente existen mecanismos ya establecidos. Es solo que es posible que no se usen para la optimización que ha sugerido. Tendría que implementar un software que realizara la comparación de lectura / escritura.

Comunidad
fuente
También es posible acceder a los valores actuales en los registros de caché, pero es algo peligroso hacerlo. Huh, esto no tiene sentido. ¿Te refieres a los registros de la CPU? Compilador genera o escritos a mano código asm usos registros a valores de retención que se está operando ...
Peter Cordes
Si está intentando implementar esto en el software, simplemente haría que el compilador genere código que lo haga en if (mem != x) { mem = x; }lugar de hacerlo mem = x;. Esto solo es a veces una optimización para líneas de caché compartidas en un programa de subprocesos múltiples, porque la escritura interfiere con la lectura de otros hilos.
Peter Cordes
1
"gruñir" no tiene nada que ver con esto. Es solo fisgonear pasivamente. Las memorias caché de la CPU usan MESI para que puedan tener memorias caché coherentes de reescritura.
Peter Cordes
@ PeterCordes Si mi respuesta es desagradable, me disculpo. Sin embargo, parece que tienes más información que yo sobre el asunto. Entonces, ¿por qué no responde la pregunta usted mismo? Mi respuesta fue obviamente inadecuada para sus estándares ...
3

Escribir en el caché L1 es una operación muy, muy crítica de tiempo.

Escribir exactamente los mismos datos parece ser bastante raro. Una optimización que acelere las cosas en este caso particular no va a tener mucha aceleración en total.

Por otro lado, esta optimización requiere una comparación de datos antiguos y nuevos en cada escritura en la memoria caché. ¡Lo que empeora esto es que requiere que los datos a escribir estén realmente disponibles en el momento de la escritura!

Ese no suele ser el caso en una CPU moderna. Los datos que se escribirán aún pueden calcularse, por ejemplo. El caché puede seguir adelante, cargar la línea de caché si es necesario, marcar la línea de caché como modificada, etc., incluso antes de que finalice el cálculo. Toda la contabilidad ya se puede realizar, excepto la modificación real de la línea de caché. Si desea comparar los resultados recién escritos y los datos de la línea de caché anterior, eso no es posible.

Como ejemplo, si tiene el código C a [i] = x / y; La división x / y tarda mucho tiempo en realizarse en la mayoría de las CPU. Sin embargo, la mayor parte del trabajo necesario para manejar el almacenamiento del resultado en un [i] ha sucedido mucho antes de que finalice la división; lo único que falta es el movimiento de ocho bytes de resultados a la línea de caché. Una operación que vacía la línea de caché esperará automáticamente hasta que finalice la división. Una operación que lee un [i] probablemente será redirigida para obtener el resultado directamente desde el divisor.

gnasher729
fuente
Un caché que usa MESI para coherencia aún podría hacer la RFO, pero si los datos se comparan una vez que están listos, deje la línea en estado Exclusivo en lugar de Modificado. La verdadera razón por la que no se hace en hardware es que cuesta lecturas adicionales de caché a medida que los datos se comprometen con la caché, y requeriría una especie de ciclos de lectura / comparación / escritura atómica (con la configuración opcional del bit sucio) que hace que succione implementación canalizada.
Peter Cordes
1

Una posible optimización sería hacer que el caché compare los contenidos de la escritura y los contenidos anteriores del caché, y si son iguales, no marque la línea como sucia

¿Esa optimización no duplicará el tiempo que la CPU necesita para escribir algo en la memoria caché? Porque cada escritura de línea de caché ahora estará acompañada de una operación de comparación, que no es gratuita.

Entonces, en realidad, la optimización ahora dependerá del factor muy vago: cuántas veces un software promedio reescribe su memoria almacenable en caché con los mismos datos.

Vladislav Rastrusny
fuente
Esta comparación se implementaría dentro de la lógica de la CPU. No requeriría una operación de CPU adicional, pero el tiempo de señal podría aumentar, lo que podría ser un problema o no.
ziggystar
@ziggystar Bueno, no soy un maestro de hardware, pero me acostumbré a la idea de que todo tiene un costo. Entonces, compara la operación con la línea de caché. Puede ser rapido. Pero esto sigue siendo un costo. Y creo que los implementadores decidieron no pagarlo. Puede ser incluso después de pensar y medir.
Vladislav Rastrusny
1
Pero está hablando del tiempo, donde el costo solo puede ser un aumento en el número de puertas.
ziggystar
1
@ziggystar: Esto no es solo más puertas. Cuando los datos se envían al caché, normalmente el proceso de envío de datos puede marcar la línea del caché como modificada. Con esta "optimización", los datos antiguos y los nuevos deben pasar a través de estas puertas, lo que causará cierto retraso, y solo entonces se puede invalidar el caché. Debe comprimir todo esto en un ciclo de procesador, de lo contrario, escribir en una línea de caché de repente toma dos ciclos. Y ahora para complicar las cosas, considere lo que sucede cuando escribo ocho palabras consecutivas en una línea de caché.
gnasher729
1
Y cada una de estas escrituras retrasa la decisión de si se modifica la línea de caché. Entonces, cuando ocurre la segunda escritura, la línea de caché no sabe si está modificada o no (todavía). Esto va a ser divertido.
gnasher729