me queda claro en el uso de MemoryBarrier, pero no en lo que sucede detrás de las escenas en el tiempo de ejecución. ¿Alguien puede dar una buena explicación de lo que sucede?¿Alguien puede dar una explicación fácil de cómo se implementan 'Full Fences' en .Net usando Threading.MemoryBarrier?
Respuesta
En un modelo de memoria muy fuerte, que emiten instrucciones de cercas serían innecesarias. Todos los accesos a memoria se ejecutarían en orden y todas las tiendas serían visibles globalmente.
Las vallas de memoria son necesarias porque las arquitecturas comunes actuales do not provide a strong memory model - x86/x64 pueden, por ejemplo, reordenar lecturas relativas a escrituras. (Una fuente más a fondo es "Intel® 64 and IA-32 Architectures Software Developer’s Manual, 8.2.2 Orden Memoria en P6 y más familias de procesadores recientes"). A modo de ejemplo de los tropecientos millones, Dekker's algorithm will fail on x86/x64 sin vallas.
Incluso si el JIT produce código de máquina en el que las instrucciones con un montón de memoria y las tiendas están cuidadosamente colocados, sus esfuerzos son inútiles si la CPU a continuación, vuelve a organizar estas cargas y tiendas - que se puede, siempre y cuando la ilusión de coherencia secuencial se mantiene durante el actual contexto/hilo
. Arriesgando la simplificación excesiva: puede ayudar a visualizar las cargas y las reservas resultantes de la secuencia de instrucciones como un rebaño atronador de wil d animales. Al cruzar un estrecho puente (CPU), nunca se puede estar seguro acerca de la orden de los animales, ya que algunos de ellos será más lenta, algunos más rápido, algunos de alcance, algunos caen atrás. Si al principio, cuando emite el código de máquina, los divide en grupos colocando vallas infinitamente largas entre ellos, puede al menos estar seguro de que el grupo A viene antes del grupo B.
Las cercas aseguran el orden de las lecturas y escribe.La redacción no es exacta, pero:
- una valla de la tienda "espera" a que finalicen todas las operaciones pendientes de la tienda (escritura), pero no afecta a las cargas.
- una valla de carga "espera" a que concluyan todas las operaciones de carga pendientes (lectura), pero no afecta a las tiendas.
- una valla completa "espera" a que finalicen todas las operaciones de almacenamiento y carga. Tiene el efecto de que se lee y se escribe antes de que la cerca se ejecute antes de las escrituras y las cargas que están en el "otro lado de la valla" (vienen después de la valla).
Lo que el JIT emite para una cerca completa, depende de la arquitectura (CPU) y de las garantías de pedido de memoria que proporciona. Dado que el JIT sabe exactamente en qué arquitectura se ejecuta, puede emitir la (s) instrucción (es) correcta (s).
En mi máquina x64, con .NET 4.0 RC, resulta ser lock or
.
int a = 0;
00000000 sub rsp,28h
Thread.MemoryBarrier();
00000004 lock or dword ptr [rsp],0
Console.WriteLine(a);
00000009 mov ecx,1
0000000e call FFFFFFFFEFB45AB0
00000013 nop
00000014 add rsp,28h
00000018 ret
Intel® 64 and IA-32 Architectures Software Developer’s Manual Capítulo 8.1.2:
"... operaciones cerradas serializar todas las operaciones de carga y almacenamiento en circulación (es decir, esperar a que se completen)" ... "operaciones bloqueadas son atómica con respecto a todas las demás operaciones de memoria y todos los eventos externamente visibles. Sólo captura de instrucciones y la tabla de páginas accesos puede pasar instrucciones bloqueados. Instrucciones bloqueadas se pueden utilizar para sincronizar los datos escritos por uno procesador y leer por otro procesador ".
orden de memoria instrucciones para satisfacer esta necesidad específica.
MFENCE
podría haber sido utilizado como barrera completa en el caso anterior (al menos en teoría - para uno, locked operations might be faster, para dos es might result in different behavior).MFENCE
y sus amigos se pueden encontrar en Capítulo 8.2.5 "Fortalecimiento o debilitamiento del modelo de pedido de memoria".
Hay algunas maneras más para serializar tiendas y cargas, aunque son poco prácticas o más lento que los métodos anteriores:
En el capítulo 8.3 se puede encontrar completo instrucciones de serialización como
CPUID
. También serializan el flujo de instrucciones: "Nada puede pasar una instrucción de serialización y una instrucción de serialización no puede pasar ninguna otra instrucción (lectura, escritura, instrucción recuperación, o E/S)".Si configura la memoria tan fuerte sin caché (UC), it will give you a strong memory model: no especulativo o fuera de orden accesos serán permitidos y todos los accesos aparecerá en el autobús, por lo tanto, no hay necesidad de emitir una instrucción. :) Por supuesto, esto será un poco más lento de lo habitual.
...
por lo que depende.Si hubiera una computadora con fuertes garantías de pedido, el JIT probablemente no emitiría nada.
IA64 y otras arquitecturas tienen sus propios modelos de memoria y, por lo tanto, garantizan el orden de la memoria (o la falta de ellas) y sus propias instrucciones/formas de gestionar el almacenamiento de memoria/orden de carga.
Mientras se hace una programación concurrente sin bloqueo debe preocuparse por las instrucciones del programa de reordenamiento.
instrucciones del programa de reordenamientopuede ocurrir en varias etapas:
- C#/VB.NET/F # optimizaciones del compilador
- optimizaciones del compilador JIT
- mejoras de CPU.
Las vallas de memoria son la única manera de garantizar el orden particular de las instrucciones de su programa. Básicamente, la valla de memoria es una clase de instrucciones que hace que la CPU aplique una restricción de ordenamiento. vallas de memoria se pueden clasificar en tres categorías:
- vallas de carga - asegurar sin carga instrucciones de la CPU se mueven a través de las vallas
- vallas Store - asegúrese de no almacenar instrucciones de la CPU se mueven a través de las vallas
- vallas completa - garantizar que no se instrucciones de carga de CPU o tienda mueven a través de las vallas
En .NET Framework hay un montón de maneras de emitir vallas: de enclavamiento, monitor, etc. ReaderWriterLockSlim
Thread.MemoryBarrier emite una valla completa tanto en el compilador JIT como en el nivel del procesador.
Tu última frase es lo que estoy buscando. Soy consciente de qué son las vallas y por qué son necesarias, pero ¿cómo se emiten en el compilador JIT y qué se está emitiendo realmente? – Kilhoffer
- 1. ¿Alguien puede dar una explicación simple de alto nivel a un principiante sobre cómo funciona Hadoop?
- 2. ¿Alguien puede dar una explicación clara de por qué Google Guice es útil?
- 3. ¿Cómo se llama una compatibilidad ioctl desde el espacio de usuario? ¿Alguien puede dar algunos ejemplos?
- 4. ¿alguien me puede dar un ejemplo de Two_line_list_item en Android?
- 5. ¿Alguien puede dar un ejemplo de cómo publicar XML usando HTTParty y Ruby on Rails?
- 6. ¿Cómo se implementan las expresiones regulares en .NET?
- 7. ¿Puede alguien darme una buena explicación del comportamiento de 'envío' para tomas sin bloqueo?
- 8. ¿Alguien puede decirme cómo crear una rama REMOTO usando smartgit?
- 9. ¿Cómo se implementan las enumeraciones en Java?
- 10. ¿Qué es una conversión de captura en Java y alguien me puede dar ejemplos?
- 11. ¿Alguien puede dar un ejemplo exacto de la implementación de la vista web en Android
- 12. ¿Cómo se puede heredar de una clase sellada usando la reflexión en .Net?
- 13. ¿Alguien puede dar una guía sobre la instalación de TFS Build en una función de Windows Azure?
- 14. ¿Cómo se puede pasar una Lista <objetos que implementan una interfaz> a un método?
- 15. ¿Cómo se implementan las referencias débiles?
- 16. ¿Alguien escribe aplicaciones de escritorio con .NET?
- 17. ¿Cómo se implementan las matrices en Perl?
- 18. ¿Cómo se implementan las matrices en Java?
- 19. ¿Cómo se implementan los analizadores DOM?
- 20. ¿Puede alguien darme una descripción general de cómo funciona lucene.net?
- 21. ¿Cómo se implementan las consolas de depuración en Python?
- 22. Dar prioridad/peso a una columna usando FREETEXTTABLE
- 23. ¿Alguien me puede dar un ejemplo de cómo select() recibe una alerta para que un fd esté "listo"
- 24. ¿Alguien puede dar un código de muestra para TabHost en Android?
- 25. ¿Alguien puede explicar el eclipse.p2.profile
- 26. FULL OUTER JOIN vs. FULL JOIN
- 27. ¿Alguien usa .NET System.IO.IsolatedStorage?
- 28. Explicación breve/rápida de .net mvc
- 29. ¿Cómo se implementan las matrices asociativas en PHP?
- 30. ¿Cómo se puede implementar una variable de condición usando semáforos?
Excelente explicación. Buenos enlaces a otros recursos también. ¡Gracias! – Kilhoffer