?

Log in

No account? Create an account
nyaload

Журнал Пушыстого

Журнал Пушыстого

Previous Entry Share Next Entry
C++ volatile
nyaload
_winnie
Пытался выяснить в интернете, насколько локальные volatile переменные действительно volatile. Быстрая проверка с g++ -S -O3 показала, что компилятор их не выкидывает, но мало ли. Про локальные не нашёл, нашёл зато статью с дотошным исследованием нескольких компиляторов.

Даже с глобальными volatile переменными компиляторы могут всё перепутать. Так же там краткое понятное описание, что означает и что не означает volatile. И интересен их метод тестирования - нагенерить кучу рандомных программ, инструментировать и проследить каков на самом деле был порядок записей/чтений в память. Оказалось что всё плохо, компиляторы глючат.

Сама статья: http://www.cs.utah.edu/~regehr/papers/emsoft08-preprint.pdf

Рекомендации:
1) модули работающие с volatile собирать без оптимизации, насколько это возможно
2) оборачивать чтение-запись в volatile переменные в функции
int vol_read_int(volatile int *vp) { return *vp; }
volatile int *vol_id_int(volatile int *vp) { return vp; }

3) читать асм-код, тестировать.
Tags:

  • 1
Спасибо за ссылку, весьма познавательно.

А что, если компилятор проинлайнит эти волшебные функции? :)))
Вообще, с предсказаторами и прочими всемогуторами - даже если компилятор родит неоптимизированный код, то процессор всё равно может сделать немножко по-своему. Поэтому volatile в их исконном смысле уже неактуальны, и нужно расставлять барьеры руками.

OOO и гарантии на memory ordering мало связаны. Впрочем да, к любому коду который использует volatile чтобы якобы гарантировать ordering следует относиться с удвоенным подозрением. Особенно если не x86, на x86 все почти просто.

Проинлайнит, да.

Это шаманство, авторы статьи говорят "непонятно почему, но помогает, компилятор перестает переставлять то что не надо". Типа в компиляторах хорошо протестирован порядок вызова функций, в отличие от порядка чтений из переменных.

А в отсутствии флагов оптимизации - то и инлайнить даже не будет :)

Очень даже понятно, почему помогает.
Обрамление в функцию расставляет точки следования, загоняя компилятор в некоторые рамки.
Ну это, как в выражении i++ + ++i заменить автоинкременты на функции
preinc(i)+postinc(i) - и получаем вместо undefined уже unspecified, а если ещё немножко покрутиться, то и well defined behavior.
К волатильности это никакого отношения не имеет.

Там вообще в стандарте языка (по крайней мере C) смысл volatile не указан явно, а оставлен на определение компиляторописателям. Потому что-то может компилироваться и работать очень странно (пример), ибо недотестировали или бросили делать volatile на полпути.

  • 1