Re[4]: volatile у переменной класса
От: Mr. None Россия http://mrnone.blogspot.com
Дата: 22.06.05 03:59
Оценка:
Здравствуйте, Alex Alexandrov, Вы писали:

AA>Ох, зря эту ветку подняли... Рекомендую прочитать все перед высказыванием мыслей.


AA>Вкратце:

А если в подробностях ? Может статью на эту тему, а то ощущается некая нехватка собранной и структурирванной информации на эту тему, причём на русском языке (помните главную идеологию RSDN — обширный портал для руско-говорящих программистов )

Вопрос.
Как-то в одной из веток (возможно даже в этой — сейчас уже не найду) проскакивало такое заявление: поскольку явных механизмов установки барьера памяти в C++ нет, то неявным является вызов обычной функции (вроде как компилятор должен обеспечить генерацию такого кода). То есть насколько я понял вызов функции (возможно специально оформленной — естественно inline функций это не касается ) гарантировано заставляет процессор перечитывать даные из памяти и тем самым решается проблема переупорядочивании комманд. Насколько это утверждение близко к действительности, из чего оно следует и можно ли его принять на вооружение, как гарантированное средство? Вызов каких именно функции приводит к таком поведению или всех кроме подставляемых?
Компьютер сделает всё, что вы ему скажете, но это может сильно отличаться от того, что вы имели в виду.
Re[5]: volatile у переменной класса
От: MaximE Великобритания  
Дата: 22.06.05 05:58
Оценка:
Здравствуйте, Mr. None, Вы писали:

AA>>Вкратце:

MN>А если в подробностях ? Может статью на эту тему, а то ощущается некая нехватка собранной и структурирванной информации на эту тему, причём на русском языке (помните главную идеологию RSDN — обширный портал для руско-говорящих программистов )

В ветке были приведены все необходимые ссылки на док-цию Intel, Microsoft, POSIX, etc..
Re[6]: volatile у переменной класса
От: Mr. None Россия http://mrnone.blogspot.com
Дата: 22.06.05 06:07
Оценка:
Здравствуйте, MaximE, Вы писали:

ME>Здравствуйте, Mr. None, Вы писали:


AA>>>Вкратце:

MN>>А если в подробностях ? Может статью на эту тему, а то ощущается некая нехватка собранной и структурирванной информации на эту тему, причём на русском языке (помните главную идеологию RSDN — обширный портал для руско-говорящих программистов )

ME>В ветке были приведены все необходимые ссылки на док-цию Intel, Microsoft, POSIX, etc..


А где это ообщение... я его найти не могу — тогда мельком просмотрел, а сейчас хочется прочитать по подробнее...
Компьютер сделает всё, что вы ему скажете, но это может сильно отличаться от того, что вы имели в виду.
Re[7]: volatile у переменной класса
От: MaximE Великобритания  
Дата: 22.06.05 06:17
Оценка:
Mr. None wrote:

[]

> ME>В ветке были приведены все необходимые ссылки на док-цию Intel, Microsoft, POSIX, etc..

>
> А где это ообщение... я его найти не могу — тогда мельком просмотрел, а сейчас хочется прочитать по подробнее...

Боюсь, что тебе придется прочитать всю ветку со всеми ссылками.

--
Maxim Yegorushkin
Posted via RSDN NNTP Server 1.9
Re[8]: volatile у переменной класса
От: vanishing  
Дата: 22.06.05 06:19
Оценка: 2 (2) +2
E>А что ему мешает их вставлять, интересно? Не вставляет — такова реализация. Но барьеры без volatile особого смысла не имеют. Если программа с глубокой оптимизацией и параллелизмом правильно работает без volatile — это либо недостатки компилятора, либо счастливое стечение обстоятельств.

ну. это вы погорячились. по работе постоянно приходится писать программы с глубокой оптимизацией и параллелизмом. и ещё ни разу не пришлось воспользоваться volatile. ибо единственное место, где эти переменные полезны — это всякие там подобия флажков. но это такой бедный и не гибкий механизм синхронизации, что используется очень и очень редко. в моём случае никогда. кроме этого по своему хобби знаю, что и в ядре ОС можно преспокойно обойтись без подобных переменных. просто надо правильно проектировать архитектуру. вот тут, конечно, я не очень понимаю, зачем автору такая переменная понадобилась, но вот распределённый счётчики, который тут упоминались или флажки done — не самое лучшее решение. ибо активное ожидание или подсчёт не каких-то событий, а количеств исполнения инструкции добавления значения — это очевидное зло.

E>То есть, значение выражения является его основным результатом, а отнюдь не побочным эффектом. И ничто не

E>У тебя — ерунда, на деле — истина

ME>> На POSIX все барьеры работают без volatile.


E>Что значит "на POSIX"? С каких пор POSIX стал как-то влиять на особенности оптимизации сишного кода? Это, как ты выразился в отношении i86 — стечение обстоятельств.


это не стечение обстоятельств : ). по опыту знаю, что на alpha, powerpc и xscale всё тоже корректно работает. просто это ведь очевидно. если в функцию примитива синхронизации передаётся указатель на переменную, то, какой бы ни была оптимизация в компиляторе, он просто обязан значение этой переменной сохранить в память, а затем уже вызывать функцию. дальнейшее — дело техники и специфичной для неё реализации примитива синхронизации. если же речь о глобальных переменных, то опять же. компилятор си (это особенность языка) не может знать, с какими именно ячейками в глобальной памяти будет работать та или иная функция, особенно, если речь идёт о вызове функции из другого модуля. поэтому все глобальные переменные, в том числе и static (чёрт ведь знает, куда что указывает) опять сохраняются в память. соответсвенно, после вызова функций, обращения к ним включают чтение из памяти.

volatile был полезен, пока человечество искало подходы к многопоточному программированию. но сейчас, imho, от него никакой пользы. одно лишь смущение умов. лишние знания ограничивают свободу творчества. вот человек вместо того, чтобы творить. сидит и разбирается, а что же такое volatile есть.
Re[5]: volatile у переменной класса
От: Alex Alexandrov США  
Дата: 22.06.05 18:35
Оценка: 55 (5) +1
Здравствуйте, Mr. None, Вы писали:

MN>А если в подробностях ? Может статью на эту тему, а то ощущается некая нехватка собранной и структурирванной информации на эту тему, причём на русском языке (помните главную идеологию RSDN — обширный портал для руско-говорящих программистов )


Я подумаю над этим. Макс, порецензируешь, если что?

MN>Вопрос.

MN>Как-то в одной из веток (возможно даже в этой — сейчас уже не найду) проскакивало такое заявление: поскольку явных механизмов установки барьера памяти в C++ нет, то неявным является вызов обычной функции (вроде как компилятор должен обеспечить генерацию такого кода). То есть насколько я понял вызов функции (возможно специально оформленной — естественно inline функций это не касается ) гарантировано заставляет процессор перечитывать даные из памяти и тем самым решается проблема переупорядочивании комманд. Насколько это утверждение близко к действительности, из чего оно следует и можно ли его принять на вооружение, как гарантированное средство? Вызов каких именно функции приводит к таком поведению или всех кроме подставляемых?

Не стоит путать барьеры компилятора и барьеры памяти.

Барьер компилятора не имеет никакого отношения к процессору. Условно говоря, для компилятора регистры процессора являются этаким кэшем нулевого уровня — он помещает в них локальные или глобальные данные для ускорения работы с ними. Одним из основных свойств кэша является время жизни в нем данных, т.е. время жизни соответствия кэшированных данных и их оригинала. Так вот барьер компиляции разрывает эту связь, вынуждая компилятор перезагрузить данные в регистры из памяти. Таким барьером является либо применение спецификатора volatile при объявлении переменной (в этом случае компилятор не имеет права кэшировать эту ячейку в регистре, он может это делать только на малое время и только если машинную инструкцию иным образом исполнить не получается), либо вызов внешней функции, т.е. функции, которая находится в другой единице компиляции и про которую компилятор, таким образом, не знает какие регистры могли измениться во время работы этой функции.

Барьер процессора — совершенно другая штука. Современные процессоры (не x86, но Итаниум и какие-то еще) могут (не могут as in умеют, а могут as in позволяют себе) переупорядочивать инструкции записи в память. Т.е. мы выполняем код

* записать число 1 в ячейку памяти A
* записать число 2 в ячейку памяти B
* записать число 3 в ячейку памяти С


но внешний наблюдатель может увидеть эти обновления в любой из 6 перестановок. Для упорядочивания этого процесса на процессорах с таким свойствами имеются специальные инструкции барьеров. Барьер может быть с одной из следующих семантик: acquire, release или full. Ссылки на материалы по этому есть в ветке.

Оба барьера необходимы для правильной работы в многопроцессорной среде при простом доступе к памяти (без использования примитивов синхронизации или атомарных инструкций — например, в многократно рассмотренном примере с глобальной булевой переменной). Именно поэтому в общем случае просто volatile недостаточно. Хотя есть частные случаи, когда его хватит:

1. На x86, поскольку здесь нет процессорного переупорядочивания.
2. Компилятор может знать о необходимости генерации процессорного барьера вдобавок к своему. Например, у Intel Compiler для Itanium есть опция /Qserialize-volatile. По умолчанию, правда, выключена.

Но самый надежный способ — все-таки примитивы синхронизации и атомарные Interlocked* функции. Как жаль, правда, что в Posix нет аналогов Interlocked*. Понимаю, что дань независимости от конкретных возможностей процессоров, но все равно жаль...
... << RSDN@Home 1.1.4 beta 7 rev. 447>>
It's kind of fun to do the impossible (Walt Disney)
Re[6]: volatile у переменной класса
От: Mr. None Россия http://mrnone.blogspot.com
Дата: 23.06.05 03:17
Оценка: +1 :))) :)))
Здравствуйте, Alex Alexandrov, Вы писали:

AA>Здравствуйте, Mr. None, Вы писали:


MN>>А если в подробностях ? Может статью на эту тему, а то ощущается некая нехватка собранной и структурирванной информации на эту тему, причём на русском языке (помните главную идеологию RSDN — обширный портал для руско-говорящих программистов )


AA>Я подумаю над этим. Макс, порецензируешь, если что?


Процензирует, процензирует!!! ДА-А-ЁШЬ СТА-АТЬЮ!!!! Восстановим репутацию родного города, изрядно подмоченную господином Губановым ...
Компьютер сделает всё, что вы ему скажете, но это может сильно отличаться от того, что вы имели в виду.
Re[6]: volatile у переменной класса
От: MaximE Великобритания  
Дата: 23.06.05 08:40
Оценка: 7 (1)
Здравствуйте, Alex Alexandrov, Вы писали:

AA>Здравствуйте, Mr. None, Вы писали:


MN>>А если в подробностях ? Может статью на эту тему, а то ощущается некая нехватка собранной и структурирванной информации на эту тему, причём на русском языке (помните главную идеологию RSDN — обширный портал для руско-говорящих программистов )


AA>Я подумаю над этим. Макс, порецензируешь, если что?


Не вопрос. Но я думаю, лучше об этом попросить Александра Терехова — он реальный перец в этих вопросах.

[]

AA>Но самый надежный способ — все-таки примитивы синхронизации и атомарные Interlocked* функции. Как жаль, правда, что в Posix нет аналогов Interlocked*. Понимаю, что дань независимости от конкретных возможностей процессоров, но все равно жаль...


На практике, под POSIX пишут на gcc, или компиляторе, совместимым с gcc (Intel). Поэтому IMO безопасно полагаться, что присутствуют ф-ции libstdc++ __gnu_cxx::__exchange_and_add и __gnu_cxx::__atomic_add.
Re[2]: volatile: а можно примеры?
От: mukos Голландия  
Дата: 24.06.05 10:40
Оценка:
Здравствуйте, eao197, Вы писали:

E>Добрый день всем.



Я думаю так —
что во всех вышеприводимых примерах в потоках использовались
функции практически ничего не делающие поэтому естественно компилятор имел полное право
забить переменную в регистр и читать ее только оттуда (без применения violatile)а втором потоке допустим
писал значение в память поэтому происходило зацикливание процесса т.е. в данном конкретном
случае имеет смысл указывать violatile (чтобы переменная каждый раз сливалась читалась из памяти) но я не вижу здесь смысла использовать обьекты
синхронизации поскольку запись или чтение переменной если и не происходят за один такт
то по крайней мере я не думаю что переключение контекста потока произойдет во время выполнения операциию.
Я использую синхронизацию в основном где может идти чтение запись данных которые могут быть непрочитаны \недозаписаны
между переключением контекста.
Но в конкретных приложениях выполняются какие либо операции (я имею в виду не просто i++и в ходе их выполнения
для освобождения регистра его все равно приходиться сливать в память хотя это видимо не 100% гарантия
поэтому думаю что имеет смысл пользовать violatile хотя бы для очистки совести.....
до прочтения этой ветки я не испльзовал violatile и не сталкивался с проблемами его не использования но теперь думаю буду
Всегда хочется быть лучше
Весь мир — Кремль, а люди в нем — агенты
Re[3]: volatile: а можно примеры?
От: Rakafon Украина http://rakafon.blogspot.com/
Дата: 30.07.09 15:23
Оценка:
Здравствуйте, mukos, Вы писали:

M>Я думаю так -

M>до прочтения этой ветки я не испльзовал violatile и не сталкивался с проблемами его не использования но теперь думаю буду

А я вот, во время проектирования приложений (в том числе и кроссплатформенных), всегда, следуя правилам хорошего тона, синхронизировал конкурентные данные с помощью соответствующих примитивов синхронизации (сперва самописных, реализованных через Crirical Section на винде и через pthreads на линуксе, потом — запользовал boost::recursive_mutex), но никогда volatile не пользовал, ибо мне не совсем было ясно на фига это делать, а теперь, после прочтения всей ветки, гарантированно никогда volatile не заюзаю, ибо понял, что юзать квалификатор volatile реально незачем!

P.S.: ... да, и кстати, как там на счёт статьи? ... чтобы коллег просвещать не 25-страничным тредом на форуме, а лаконично изложенной грамотной статьёй с примерами сорцов! Кто нибудь из уважаемых <b>Alex Alexandrov</b>, <b>MaximE</b> или Александр Терехов, взялся за это благое дело?
"Дайте мне возможность выпускать и контролировать деньги в государстве и – мне нет дела до того, кто пишет его законы." (c) Мейер Ансельм Ротшильд , банкир.
volatile
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.