La CPU (su controlador de memoria específicamente) puede aprovechar el hecho de que la memoria no está mutada
La ventaja es que este hecho evita que el compilador use instrucciones membares cuando se accede a los datos.
Una barrera de memoria, también conocida como instrucción membar, cerca de memoria o cerca, es un tipo de instrucción de barrera que hace que una unidad central de procesamiento (CPU) o compilador imponga una restricción de orden en las operaciones de memoria emitidas antes y después de la instrucción de barrera. Esto generalmente significa que se garantiza que ciertas operaciones se realicen antes de la barrera y otras después.
Las barreras de memoria son necesarias porque la mayoría de las CPU modernas emplean optimizaciones de rendimiento que pueden resultar en una ejecución fuera de orden. Este reordenamiento de las operaciones de memoria (cargas y almacenes) normalmente pasa desapercibido dentro de un solo hilo de ejecución, pero puede causar un comportamiento impredecible en programas concurrentes y controladores de dispositivos a menos que se controlen cuidadosamente ...
Verá, cuando se accede a los datos desde diferentes subprocesos, en la CPU de varios núcleos se realiza de la siguiente manera: diferentes subprocesos se ejecutan en diferentes núcleos, cada uno con su propia caché (local a su núcleo), una copia de alguna caché global.
Si los datos son mutables y el programador necesita que sean consistentes entre diferentes hilos, se deben tomar medidas para garantizar la coherencia. Para el programador, esto significa usar construcciones de sincronización cuando acceden (por ejemplo, leen) a datos en un hilo particular.
Para el compilador, la construcción de sincronización en el código significa que necesita insertar una instrucción membar para asegurarse de que los cambios realizados en la copia de datos en uno de los núcleos se propaguen correctamente ("publicados"), para garantizar que los cachés en otros núcleos tener la misma copia (actualizada).
Algo más simple, vea la nota a continuación , esto es lo que sucede en el procesador multinúcleo para membar:
- Todos los núcleos detienen el procesamiento , para evitar escribir accidentalmente en la memoria caché.
- Todas las actualizaciones realizadas en las memorias caché locales se vuelven a escribir en una global, para garantizar que la memoria caché global contenga los datos más recientes. Esto lleva algo de tiempo.
- Los datos actualizados se vuelven a escribir del caché global a los locales, para garantizar que los cachés locales contengan los datos más recientes. Esto lleva algo de tiempo.
- Todos los núcleos reanudan la ejecución.
Verá, todos los núcleos no hacen nada mientras los datos se copian de un lado a otro entre cachés globales y locales . Esto es necesario para garantizar que los datos mutables estén correctamente sincronizados (seguro para subprocesos). Si hay 4 núcleos, los 4 se detienen y esperan mientras se sincronizan los cachés. Si hay 8, los 8 se detienen. Si hay 16 ... bueno, tienes 15 núcleos que no hacen exactamente nada mientras esperas las cosas que debes hacer en uno de estos.
Ahora, veamos qué sucede cuando los datos son inmutables. No importa a qué hilo acceda, se garantiza que sea el mismo. Para el programador, esto significa que no es necesario insertar construcciones de sincronización cuando acceden (leen) a los datos en un subproceso particular.
Para el compilador, esto a su vez significa que no es necesario insertar una instrucción membar .
Como resultado, el acceso a los datos no necesita detener los núcleos y esperar mientras los datos se escriben de un lado a otro entre cachés globales y locales. Esa es una ventaja del hecho de que la memoria no está mutada .
Tenga en cuenta que la explicación un poco simplificada anterior elimina algunos efectos negativos más complicados de que los datos sean mutables, por ejemplo, en la canalización . Para garantizar el pedido requerido, la CPU tiene que invalidar las líneas de pilotes afectadas por los cambios de datos; esa es otra penalización de rendimiento. Si esto se implementa mediante la invalidación directa (y por lo tanto confiable) de todas las tuberías, entonces el efecto negativo se amplifica aún más.