velocidades procesadores microprocesadores lake cronologia coffee caracteristicas broadwell c# .net intel

c# - procesadores - ¿Es la lectura doble atómica en una arquitectura Intel?



velocidades de procesadores intel (3)

Mi colega y yo estamos discutiendo sobre la atomicidad de leer un doble en una arquitectura Intel usando C # .NET 4.0.

Intel garantiza que los dobles de 8 bytes son atómicos en lectura y escritura cuando se alinean con un límite de 8 bytes .

C # no garantiza que un doble esté alineado con un límite de 8 bytes.

Él está argumentando que deberíamos usar el método Interlocked.Exchange para escribir en un doble, pero solo leer el valor doble (en algún otro hilo) está garantizado para ser atómico.

Tu colega no está pensando en esto cuidadosamente. Las operaciones entrelazadas son solo atómicas con respecto a otras operaciones entrelazadas . No tiene ningún sentido utilizar operaciones entrelazadas algunas veces; esto es como decir que el tráfico que atraviesa la intersección hacia el norte no tiene que obedecer al semáforo porque el tráfico que atraviesa la intersección hacia el oeste obedece al semáforo. Todo el mundo tiene que obedecer las luces para evitar colisiones; No puedes hacer solo la mitad.

Mi argumento es que .NET no garantiza esta atomicidad, pero su argumento es que en una arquitectura Intel esto está garantizado (quizás no en AMD, SPARC, etc.).

Mira, supongamos que ese argumento fuera correcto, lo que no es. ¿La conclusión a la que se supone que debemos llegar aquí es que los varios nanosegundos que se salvan al hacerlo mal valen el riesgo? Olvídate de entrelazado. Tome un bloqueo completo cada vez . La única vez que no debe tomar un bloqueo completo cuando comparte memoria a través de subprocesos es cuando tiene un problema de rendimiento demostrado que en realidad se debe a la sobrecarga de doce nanosegundos del bloqueo. Esto es cuando una penalización de doce nanosegundos es la cosa más lenta en su programa y eso sigue siendo inaceptable , ese es el día que debe considerar usar una solución de bloqueo bajo. ¿Es lo más lento en su programa tomar un bloqueo incontenido de 12 nanosegundos? ¿No? Entonces deje de tener este argumento y dedique su valioso tiempo a hacer que las partes de su programa tomen más de 12 nanosegundos más rápido.

El lector está bien para leer un valor obsoleto (anterior), pero no un valor incorrecto (lectura parcial antes y después de la escritura que da un valor de basura).

No confunda la atomicidad con la volatilidad.

Las operaciones entrelazadas, y la declaración de bloqueo, harán una barrera de memoria que asegure que el valor actualizado se lea o publique. No se requiere una lectura o escritura no volátil ordinaria para hacerlo; Si lo hace, tienes suerte.

Si le interesan este tipo de problemas, un problema relacionado que ocasionalmente me preguntan es en qué circunstancias puede eliminarse un bloqueo alrededor de un acceso de número entero. Mis artículos sobre ese tema son:

Mi colega y yo estamos discutiendo sobre la atomicidad de leer un doble en una arquitectura Intel usando C # .NET 4.0. Él está argumentando que deberíamos usar el método Interlocked.Exchange para escribir en un double , pero solo leer el valor doble (en algún otro hilo) está garantizado para ser atómico. Mi argumento es que .NET no garantiza esta atomicidad, pero su argumento es que en una arquitectura Intel esto está garantizado (quizás no en AMD , SPARC , etc.).

¿Algún experto en Intel y .NET comparten algunas luces sobre esto?

El lector está bien para leer un valor obsoleto (anterior), pero no un valor incorrecto (lectura parcial antes y después de la escritura que da un valor de basura).


Leer o escribir un doble es atómico en la arquitectura Intel si están alineados en un límite de dirección de 8 bytes. Ver Está actualizando doble operación atómica .

A pesar de que las lecturas y las escrituras de dobles pueden ser efectivamente atómicas en el código .NET de la arquitectura Intel, no lo confiaría ya que la especificación de C # no lo garantiza, vea esta cita de una Respuesta de Eric Lippert .

Las lecturas y escrituras de los siguientes tipos de datos son atómicas: bool, char, byte, sbyte, short, ushort, uint, int, float y tipos de referencia. Además, las lecturas y escrituras de tipos de enumeración con un tipo subyacente en la lista anterior también son atómicas. No se garantiza que las lecturas y escrituras de otros tipos, incluidos long, ulong, double y decimal, así como las definidas por el usuario, sean atómicas.

Use Interlocked para leer y escribir para estar seguro. Garantiza la atomicidad. En una arquitectura en la que es atómico por defecto, no debería generar ningún gasto general. Interlocked utilizar Interlocked para la lectura y la escritura para asegurarse de que no se lean valores escritos parcialmente ( cita de la documentación de InterLocked.Read() ):

El método de Lectura y las sobrecargas de 64 bits de los métodos de Incremento, Disminución y Adición son verdaderamente atómicos solo en sistemas donde un System.IntPtr tiene una longitud de 64 bits. En otros sistemas, estos métodos son atómicos entre sí, pero no con respecto a otros medios de acceso a los datos. Por lo tanto, para estar a salvo de subprocesos en sistemas de 32 bits, cualquier acceso a un valor de 64 bits se debe realizar a través de los miembros de la clase Interlocked.


Si y no. En los procesadores de 32 bits, no se garantiza que sea atómico, porque el doble es más grande que el tamaño nativo de la palabra. En un procesador de 64 bits, el acceso correctamente alineado es atómico. La CLI 64 bits garantiza todo hasta una lectura de 64 bits como atómica. Así que necesitarías construir tu ensamblaje para x64 (no cualquier CPU ). De lo contrario, si su ensamblaje puede ejecutarse en 32 bits, mejor use Interlocked , vea Atomicidad, volatilidad e inmutabilidad son diferentes, parte dos por Eric Lippert. Creo que puede confiar en el conocimiento de Eric Lippert sobre el CLR Microsoft.

El estándar ECMA CLI también lo admite, aunque C # en sí no lo garantiza:

Un CLI conforme debe garantizar que el acceso de lectura y escritura a las ubicaciones de memoria correctamente alineadas que no sean mayores que el tamaño de palabra nativo (el tamaño del tipo nativo int) es atómico (consulte §I.12.6.2)

También dice que en los procesadores donde las operaciones son atómicas, los métodos entrelazados a menudo se compilan en una sola instrucción, por lo que en mi libro no hay una penalización de rendimiento al usarla. Por otro lado, puede haber una penalización peor por no usarlo cuando debería.

Otra pregunta relacionada sobre el desbordamiento de pila es: ¿Qué operaciones son atómicas en C #? .