¿Qué tipo de optimizaciones previene ‘volátil’ en C ++?

Estaba buscando la palabra clave volatile y para qué sirve, y la respuesta que obtuve fue más o menos:

Se usa para evitar que el comstackdor optimice el código ausente.

Hubo algunos ejemplos, como cuando se sondeó el hardware mapeado en memoria: sin volatile el ciclo de sondeo se eliminaría ya que el comstackdor podría reconocer que el valor de la condición nunca cambia. Pero como solo había un ejemplo o tal vez dos, me puse a pensar: ¿hay otras situaciones en las que necesitemos usar volatile en términos de evitar una optimización no deseada? ¿Las variables de condición son el único lugar donde se necesita volatile ?

Me imagino que la optimización es específica del comstackdor y, por lo tanto, no está especificada en la especificación C ++. ¿Eso significa que tenemos que ir por instinto, diciendo Hm, sospecho que mi comstackdor eliminará esto si no declaro esa variable como volatile o hay reglas claras para seguir?

Básicamente, volatile anuncia que un valor puede cambiar detrás de la parte posterior de su progtwig. Eso evita que los comstackdores guarden en caché el valor (en un registro de CPU) y optimizan los accesos a ese valor cuando parecen innecesarios desde el punto de vista de su progtwig.

Lo que debería desencadenar el uso de volatile es cuando un valor cambia a pesar del hecho de que su progtwig no ha escrito en él, y cuando no hay otras barreras de memoria (como mutexes como las usadas para progtwigs de subprocesos múltiples).

El comportamiento observable de un progtwig C ++ se determina mediante lectura y escritura en variables volátiles y cualquier llamada a funciones de entrada / salida.

Lo que esto implica es que todas las lecturas y escrituras en variables volátiles deben ocurrir en el orden en que aparecen en el código, y deben suceder. (Si un comstackdor rompió una de esas reglas, estaría rompiendo la regla de si-si.)

Eso es todo. Se usa cuando necesita indicar que leer o escribir una variable se debe ver como un efecto observable. (Tenga en cuenta que el artículo “C ++ y los peligros del locking doblemente controlado” toca esto bastante).


Entonces, para responder a la pregunta del título, evita cualquier optimización que pueda reordenar la evaluación de las variables volátiles en relación con otras variables volátiles .

Eso significa un comstackdor que cambia:

 int x = 2; volatile int y = 5; x = 5; y = 7; 

A

 int x = 5; volatile int y = 5; y = 7; 

Está bien, ya que el valor de x no es parte del comportamiento observable (no es volátil). Lo que no estaría bien es cambiar la asignación de 5 a una asignación a 7, porque esa escritura de 5 es un efecto observable.

Las variables de condición no son donde se necesita volatile ; estrictamente solo es necesario en los controladores de dispositivo.

volatile garantías volatile que lee y escribe en el objeto no se optimizan ni se reordenan con respecto a otro volatile . Si está ocupado, haciendo un bucle en una variable modificada por otro hilo, debe declararse volatile . Sin embargo, no deberías busy-loop. Debido a que el lenguaje no fue realmente diseñado para multihilo, esto no está muy bien soportado. Por ejemplo, el comstackdor puede mover una escritura a una variable no volátil de la parte posterior a la anterior, violando el locking. (Para spinloops indefinidos, esto solo puede ocurrir en C ++ 0x).

Cuando llamas a una función de biblioteca de hilos, actúa como una valla de memoria, y el comstackdor asumirá que todos y cada uno de los valores han cambiado, esencialmente todo es volátil. Esto es especificado o tácitamente implementado por cualquier biblioteca de enhebrado para mantener las ruedas girando suavemente.

C ++ 0x podría no tener este inconveniente, ya que introduce una semántica formal de subprocesamiento múltiple. No estoy realmente familiarizado con los cambios, pero en aras de la compatibilidad con versiones anteriores, no es necesario declarar nada volátil que no fuera antes.

Volátil no intenta mantener los datos en un registro de la CPU (100 veces más rápido que la memoria). Tiene que leerlo de memoria cada vez que se usa.