2010-03-22 5 views

Respuesta

14

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.

+0

Excelente explicación. Buenos enlaces a otros recursos también. ¡Gracias! – Kilhoffer

4

Mientras se hace una programación concurrente sin bloqueo debe preocuparse por las instrucciones del programa de reordenamiento.

instrucciones del programa de reordenamiento

puede ocurrir en varias etapas:

  1. C#/VB.NET/F # optimizaciones del compilador
  2. optimizaciones del compilador JIT
  3. 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:

  1. vallas de carga - asegurar sin carga instrucciones de la CPU se mueven a través de las vallas
  2. vallas Store - asegúrese de no almacenar instrucciones de la CPU se mueven a través de las vallas
  3. 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.

+0

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

Cuestiones relacionadas