2009-07-07 20 views
35

Sé que escribir en una variable volatile lo vacía de la memoria de toda la CPU, sin embargo, quiero saber si las lecturas de una variable volátil son tan rápidas como las lecturas normales.¿Las 'lecturas' variables volátiles son tan rápidas como las lecturas normales?

Can volatile ¿Alguna vez las variables se colocan en la memoria caché de la CPU o siempre se extraen de la memoria principal?

+1

¿Podría agregar "java" en algún lugar de la pregunta? Ha habido confusiones con C: simplemente establecer la palabra clave no parece ser suficiente. –

+0

parece estar allí ahora – pdeva

Respuesta

-3

volátil implica que el compilador no puede optimizar la variable colocando su valor en un registro de CPU. Se debe acceder desde la memoria principal. Sin embargo, puede colocarse en un caché de la CPU. La caché garantizará la coherencia entre cualquier otra CPU/núcleo en el sistema. Si la memoria está asignada a IO, entonces las cosas son un poco más complicadas. Si fue diseñado como tal, el hardware evitará que ese espacio de direcciones se almacene en caché y todos los accesos a esa memoria irán al hardware. Si no existe tal diseño, los diseñadores de hardware pueden requerir instrucciones adicionales de la CPU para asegurarse de que la lectura/escritura pasa por las memorias caché, etc.

Por lo general, la palabra clave "volátil" solo se usa para controladores de dispositivo en funcionamiento sistemas.

+6

Eso puede ser lo que significa volátil en C, pero no es lo que significa en Java. En Java, la volatilidad se trata de si un hilo que realiza una lectura "verá" los cambios realizados por otro hilo. Es más que simplemente si el valor puede estar en un registro de CPU. La palabra clave volátil también evita qué tipo de reordenamiento puede hacer la JVM en el código que usa la variable. – NamshubWriter

+0

Aquí hay un artículo del Dr. Dobb que entra un poco más de detalle entre las diferencias: http://www.ddj.com/hpc-high-performance-computing/212701484 –

+0

El lector no dijo java y fue mencionado específicamente de 2do nivel caché, así que asumí el escenario más común ... C. – drudru

13

La respuesta depende de la arquitectura. En un x86, no hay gastos adicionales asociados con lecturas volátiles específicamente, aunque existen implicaciones para otras optimizaciones.

JMM cookbook from Doug Lea, see architecture table near the bottom.

Para aclarar: No hay ninguna sobrecarga adicional asociada con el propio leer. Las barreras de memoria se utilizan para garantizar el orden correcto. JSR-133 clasifica cuatro barreras "LoadLoad, LoadStore, StoreLoad y StoreStore". Dependiendo de la arquitectura, algunas de estas barreras corresponden a un "no-op", lo que significa que no se toman medidas, otras requieren una valla. No hay un costo implícito asociado con la carga en sí, aunque se puede incurrir en uno si hay una valla en su lugar. En el caso del x86, solo una barrera StoreLoad da como resultado una cerca.

Como se señala en una publicación de blog, el hecho de que la variable sea volátil significa que hay suposiciones sobre la naturaleza de la variable que ya no se pueden realizar y algunas optimizaciones del compilador no se aplicarán a un elemento volátil.

Volátil no es algo que deba usarse con ligereza, pero tampoco debe temerse. Hay muchos casos en los que bastará un volátil en lugar de un bloqueo más fuerte.

+2

¿Cómo puede ser esto? ¿Qué hay de los procesadores multi-core? (Sin leer el enlace completo que publicó) – ripper234

+6

Nada es siempre un "no-op", a menos que pueda eliminarse por completo de su programa. Las lecturas volátiles son baratas, pero no gratuitas, e inhiben la optimización de una manera que las lecturas simples no lo hacen (por ejemplo, una lectura volátil no se puede sacar de los bucles o leer de un registro). El "no-op" en este caso se refiere a la falta de instrucción de cerca correspondiente, pero la lectura en sí tiene semántica y esos tienen un costo. –

+2

Correcto. Sin embargo, esas son semánticas de optimización que están fuera de los impuestos explícitamente por los volátiles. La respuesta principal a la pregunta es "depende de la arquitectura". Por ahora el comentario es verdad. Mucha gente teme que sea volátil y eso es algo tonto. Aunque tampoco recomendaría usar volatilmente en todo. –

0

Las lecturas volátiles no pueden ser tan rápidas, especialmente en CPU de núcleos múltiples (pero también solo de núcleo único). El núcleo de ejecución debe obtener de la dirección de memoria real para asegurarse de que obtiene el valor actual; la variable no puede almacenarse en caché.

A diferencia de otra respuesta aquí, las variables volátiles son no se usan solo para controladores de dispositivos. ¡A veces son esenciales para escribir código multihilo de alto rendimiento!

+5

* Las lecturas volátiles no pueden ser tan rápidas, especialmente en CPUs multinúcleo * Esto no es totalmente cierto, en la mayoría de las lecturas volátiles de hardware solo son cargas normales. Las cargas son caras cuando falta la memoria caché, pero las lecturas volátiles no van a la memoria principal, si hay un valor en la memoria caché e incluso las escrituras volátiles (que son costosas) pueden actualizar las líneas de caché de la CPU local. Multi CPU/Socket depende del protocolo de coherencia de caché para garantizar los valores válidos pero no hace que las lecturas volátiles sean más caras. – bestsss

+0

@bestsss - bueno, admito la ignorancia de los detalles, pero siempre me enseñaron que las lecturas normales "siempre" superan las lecturas volátiles. No apostaré 1 billón de dólares en la respuesta. – ripper234

+0

No, algunas CPU pueden necesitar una barrera de carga, pero aún es barata. Como regla general, considere las lecturas volátiles solo cargas normales. Si alguna CPU necesita ir a la memoria principal (también conocida como falta de caché), es una falla de diseño horrible. – bestsss

1

Depende de la arquitectura. Lo que volatile hace es decirle al compilador que no optimice esa variable. Obliga a la mayoría de las operaciones a tratar el estado de la variable como desconocido. Debido a que es volátil, podría cambiarse por otro hilo u otra operación de hardware. Entonces, las lecturas necesitarán volver a leer la variable y las operaciones serán del tipo lectura-modificación-escritura.

Este tipo de variable se utiliza para los controladores de dispositivo y también para la sincronización con mutexes/semáforos en memoria.

+3

No relevante, la pregunta es para Java. – ripper234

+2

Sigue siendo relevante si entiende lo que significa volatilidad. – sybreon

+0

Significa algo ligeramente diferente en Java. – ripper234

16

Deberías echar un vistazo a este artículo: http://brooker.co.za/blog/2012/09/10/volatile.html.El artículo del blog argumenta que las lecturas volátiles pueden ser mucho más lentas (también para x86) que las lecturas no volátiles en x86.

  • La Prueba 1 es una lectura y escritura paralelas a una variable no volátil. No hay ningún mecanismo de visibilidad y los resultados de las lecturas son potencialmente obsoletos.
  • Prueba 2 es una lectura paralela y escritura en una variable volátil. Esto no aborda específicamente la pregunta del OP. Sin embargo, vale la pena señalar que un contendiente volátil puede ser muy lento.
  • Prueba 3 es una lectura volátil en un circuito cerrado. Demostrado es que la semántica de lo que significa ser volátil indica que el valor puede cambiar con cada iteración de bucle. Por lo tanto, la JVM no puede optimizar la lectura y sacarla del ciclo. En la Prueba 1, es probable que el valor haya sido leído y almacenado una vez, por lo que no hay una "lectura" real.

Marc Booker's tests

crédito a Marc Booker para la ejecución de estas pruebas.

+1

que parece ser el caso solo cuando se trata de la volatilidad. – pdeva

+6

@pdeva, no, el gráfico muestra claramente que las lecturas volátiles no controladas son más lentas que las no volátiles. Con un efecto llamativo, parece 2-3 veces más lento. – nilskp

Cuestiones relacionadas