¿Es double read atomic en una arquitectura Intel?


Mi colega y yo estamos teniendo un argumento 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 leyendo el doble valor (en algún otro hilo) se garantiza que es atómico. Mi argumento es que. NET no garantiza esta atomicidad, pero su argumento es que en una arquitectura Intel esto está garantizado (tal vez no en AMD, SPARC , etc.).

Cualquier Intel y. NET expertos comparten algunas luces sobre esto?

Reader está bien para leer un valor obsoleto (anterior), pero no un valor incorrecto (lectura parcial antes y después de escribir dando un valor basura).

Author: Peter Mortensen, 2014-07-14

3 answers

Sí y no. En procesadores de 32 bits, no se garantiza atomic, porque double es más grande que el wordsize nativo. En un procesador de 64 bits el acceso correctamente alineado es atómico. La CLI de 64 bits garantiza todo hasta una lectura de 64 bits como atómica. Por lo tanto, tendría que construir su ensamblaje para x64 (no Ninguna CPU). De lo contrario, si su ensamblaje puede ejecutarse en 32 bits, es mejor usar Enclavado , consulte Atomicidad, volatilidad e inmutabilidad son diferentes, parte dos por Eric Lippert. Creo que puede confiar en el conocimiento de Eric Lippert de Microsoft CLR.

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

Una CLI conforme garantizará que el acceso de lectura y escritura a ubicaciones de memoria correctamente alineadas no más grandes que el tamaño de la palabra nativa (el tamaño del tipo nativo int) es atómico (ver §I. 12.6.2)

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

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

 20
Author: codenheim,
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 10:30:49

Mi colega y yo estamos teniendo un argumento 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 al leer y escribir 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 debemos usar el método Interlocked.Exchange para escribir en un doble, pero solo leyendo el doble valor (en algún otro hilo) está garantizado para ser atómico.

Su colega no está pensando esto cuidadosamente. Las operaciones con enclavamiento solo son atómicas con respecto a otras operaciones con enclavamiento. No tiene ningún sentido usar operaciones entrelazadas algunas del tiempo; esto es como decir que el tráfico que pasa por la intersección hacia el norte no tiene que obedecer el semáforo porque el tráfico que pasa por la intersección hacia el oeste obedece el semáforo. Todo el mundo tiene que obedecer las luces para evitar colisiones; no se puede 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 (tal vez no en AMD, SPARC, etc.).

Mira, supongamos que ese argumento fuera correcto, que no lo es. ¿Es la conclusión que se supone que debemos llegar aquí es que los varios nanosegundos que se guardan al hacerlo mal son de alguna manera vale la pena el riesgo? Olvídate del entrelazado. Tome un bloqueo completo cada vez. La única vez que no debe tener un bloqueo completo al compartir memoria entre hilos es cuando tiene un problema de rendimiento demostrado que en realidad se debe a la sobrecarga de doce nanosegundos del bloqueo. Eso 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 en que debe considerar usar una solución de bloqueo bajo. Es el ¿la cosa más lenta en su programa toma una cerradura no disputada de 12 nanosegundos? ¿No? Entonces deja de tener este argumento, y pasa tu valioso tiempo haciendo las partes de tu programa que toman más que 12 nanosegundos más rápido.

Reader está bien para leer un valor obsoleto (anterior), pero no un valor incorrecto (lectura parcial antes y después de escribir dando un valor basura).

No confunda atomicidad con volatilidad.

Las operaciones entrelazadas y la instrucción lock, ambos harán una barrera de memoria que asegura que el valor actualizado sea leído o publicado. No se requiere una lectura o escritura ordinaria no volátil para hacerlo; si sucede que lo hace, tuvo suerte.

Si este tipo de problemas le interesan, un problema relacionado que de vez en cuando me preguntan es bajo qué circunstancias un bloqueo alrededor de un acceso entero puede ser eludido. Mis artículos sobre ese tema son:

 23
Author: Eric Lippert,
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
2014-07-15 00:45:18

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 la doble operación atómica.

Aunque las lecturas y escrituras de dobles podrían efectivamente ser atómicas en código.NET en la arquitectura Intel, no confiaría en ello 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. En además, lee y escribe de tipos de enumeración con un tipo subyacente en la lista anterior también es atómica. Lee y escribe de otros tipos, incluyendo long, ulong, double y decimal, así como definido por el usuario no se garantiza que sean atómicos.

Use Interlocked para que la lectura y la escritura sean seguras. Garantiza atomicidad. En una arquitectura donde es atómica por defecto, no debería producir ninguna sobrecarga. Necesitas usar Interlocked tanto para leer como para escribir para asegurarse de que no se leen valores parcialmente escritos ( cita de la documentación de InterLocked.Read() ):

El método de lectura y las sobrecargas de 64 bits del Incremento, Decremento, y los métodos Add son verdaderamente atómicos solo en sistemas donde un Sistema.IntPtr tiene 64 bits de largo. En otros sistemas, estos métodos son atómicos con con respecto a los demás, pero no con respecto a otros medios de acceder a los datos. Por lo tanto, para ser seguro en sistemas de 32 bits, cualquier el acceso a un valor de 64 bits debe hacerse a través de los miembros del Clase entrelazada.

 18
Author: Anders Abel,
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:26:38