Re[18]: volatile у переменной класса
От: achp  
Дата: 18.01.05 19:50
Оценка: 29 (4) +1 :)
Здравствуйте, emusic, Вы писали:

A>>Хм... Если есть барьер, то зачем volatile?


E>Бааалин. Глухой телефон Кто обещал, что барьер можно специфицировать на конкретный объект? Если на каждый объект сделать функцию, которая обеспечивает сливание его в память на одном процессоре и всасывание в другом — разумеется, компилятор после выполнения этой функции перечитает любую часть объекта из памяти, ибо в функцию будет передаваться неконстантная ссылка


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

Разумеется, это не касается случая, когда включена форсированная оптимизация. Ну, это уже ваш собственный выбор — у компилятора к услугам обманщиков вообще есть широчайший ассортимент способов устроить неопределенное поведение.

По мне так это несильно отличается от вот такого:

int f()
{
    char const* const p = "aaa";
    *const_cast<char*>(p) = 'b';
    const_cast<char const*&>(p) = p + 1;
}


Если же барьер не обеспечивает синхронизации памяти между процессорами, — ну тут уж извиняйте — никакое volatile вам не поможит.

E>А если барьер неспецифичный, вроде KeMemoryBarrier в виндовом ядре? Как объяснить компилятору, что после вызова некоторой функции без аргументов последнее известное значение объекта уже нельзя считать валидным? Разумеется, если не применять глубокой оптимизации — компилятор будет осторожничать и перечитывать после каждого вызова неизвестной ему функции. Указание volatile для разделяемых объектов позволит ему максимально оптимизировать остальные объекты. Если охота еще и оптимизации разделяемых объектов — значит, нужны специфичные барьерные примитивы на каждый разделяемый объект.


В Си/Си++ как языке просто нет легальных средств для такой тонкой оптимизации. То, о чём Вы пишете, относится к узкому случаю, связаннмоу с применением конкретного компилятора на конкретной платформе.

Разумеется, если ставить перед собой такие чисто практические задачи, то Вы совершенно правы.
Я кончил, джентльмены, мне остается только поблагодарить вас за внимание.
Re[8]: volatile у переменной класса
От: MaximE Великобритания  
Дата: 18.01.05 20:06
Оценка: 3 (1)
emusic wrote:

> Здравствуйте, MaximE, Вы писали:

>
> ME>Ok, ты работаешь над проектом. Менеджер спрашивает тебя, готов ли ты поставить свою зарплату, что твой многопоточный кусок кода, в котором ты не используешь ф-ций синхронизации, а полагаешься на "fuzzy" семантику volatile, заработает на не Intel SMP системе?
>
> А ты свою зарплату за то, что код, использующий функции синхронизации, но не использующий volatile, заработает везде, поставишь? Только хорошо подумай перед тем, как согласиться

Код который написал я — да.

> Макс, ты тут ругал человека, что он не читает тред — а ты сам его разве читаешь? Тебе в который раз повторяют, что для гарантированной работы кода в общем случае обязательны и функции синхронизации, и volatile. Но тебе, похоже, комфортнее делать вид, будто все, как один, сторонники volatile предлагают использовать его вместо функций синхронизации


Позволь тебя спросить: что ты думаешь про постинг Александра Терехова?

Тебе не надоело упираться рогом в стену?

Ты все еще надеешься увидеть мою реакцию на твой эмоциональный шантаж?

--
Maxim Yegorushkin
Posted via RSDN NNTP Server 1.9
Re[10]: [2]: : volatile: а можно примеры?
От: Andrew S Россия http://alchemy-lab.com
Дата: 18.01.05 20:07
Оценка:
>> а вот "недостаточно" "и поэтому ... бесполезен" — это действительно ересь хотя бы с точки зрения формальной логики

ME>Согласен, но с точки зрения треда — это оффтопик.


Максим, отнюдь. В исходном вопросе не содержится никаких предположений о том, каким образом меняется переменная одним из потоков. Для полноты изложения предположим, что это делается при помощи функции InterlockedXxx. Т.о. будет рассматривать "кошерную" синхронизацию, когда таки используются примитивы синхронизации.
Итак, чтобы больше не возникало подобных ответов, уточним условия:

1. Есть 2 или более потоков.
2. Есть разделяемая между ними переменная. long.
3. Запись (и пусть даже чтение) производится при помощи функций InterlockedExchange\InterlockedExchangeAdd или их аналогов.
4. Мы не привязываемся ни к конкретной архитектуре процессора, ни к конкретному компилятору.

Возможные варианты (V):

V1. Переменная объявлена как volatile. Соотв, параметры InterlockedXxx объявлены с volatile.
V2. Переменная объявлена не как volatile. Соотв, параметры InterlockedXxx без volatile (например, как это было в PSDK 2-х летней давности. Теперь это не так и вынуждает программистов использовать volatile для этих функций. Так что предположения о том, что этого не станут требовать разработчики компиляторов, очевидно, не оправдались).

Теперь некоторые соображения(A):

A1. Функции InterlockedXxx могут быть intrinsic (например, http://msdn.microsoft.com/library/en-us/vclang/html/vcrefCompilerIntrinsics.asp)
A2. Функции InterlockedXxx могут не быть intrinsic.

Интересуют Ваши (а не ссылки на группо-гугль, где, собственно, ничего нового нет) ответы на следующие вопросы:

(x) Случай Vx,Ax. Может ли в этом случае компилятор закэшировать значение переменной? Имеются в виду как обычные, так и наиболее агрессивные настройки оптимизации.
Итого, соотв, 4 варианта.

PS Мое мнение — volatile в данном аспекте необходимое, но не достаточное условие и должен использоваться для таких разделяемых переменных. По крайней мере, для случая Vx,A1.
http://www.rusyaz.ru/pr — стараемся писАть по-русски
Re[8]: volatile у переменной класса
От: MaximE Великобритания  
Дата: 18.01.05 20:16
Оценка:
emusic wrote:

> Тебе в который раз повторяют, что для гарантированной работы кода в общем случае обязательны и функции синхронизации, и volatile.


POSIX не требует volatile. Осталось разобраться для win32. Согласен?

> Но тебе, похоже, комфортнее делать вид, будто все, как один, сторонники volatile предлагают использовать его вместо функций синхронизации


По крайней мере, большАя часть их.

--
Maxim Yegorushkin
Posted via RSDN NNTP Server 1.9
Re[11]: [2]: : volatile: а можно примеры?
От: MaximE Великобритания  
Дата: 18.01.05 22:05
Оценка:
Andrew S wrote:

> (x) Случай Vx,Ax. Может ли в этом случае компилятор закэшировать значение переменной? Имеются в виду как обычные, так и наиболее агрессивные настройки оптимизации.

> Итого, соотв, 4 варианта.

Не будет закэшировано во всех вариантах. (если, конечно, никто не применит ключ компиляции "компайлер, здесь нет никакого альясинга, мамой клянусь!")

Если ф-ция внешняя, то компайлер просто не может "видеть" что она делает и ему придется прочитать значения из памяти. В случае с intrinsic — компайлер "знает" эффекты собственного intrinsic.

--
Maxim Yegorushkin
Posted via RSDN NNTP Server 1.9
Re[6]: [2]: : volatile: а можно примеры?
От: Шахтер Интернет  
Дата: 19.01.05 00:20
Оценка:
Здравствуйте, eao197, Вы писали:

E>Здравствуйте, Шахтер, Вы писали:


Ш>>Они уже приведены.


E>То, что я видел выше нельзя назвать примерами реальных проектов. Это небольшие тестовые программки, которые дополнены комментариями типа "вот когда-нибудь, когда придут крутые-крутые компиляторы, которые увидят, как работают WaitForSingleObject/pthread_mutex_wait, вот тогда...". И еще говорят, что компилятор справедливо опасается оптимизировать доступ к переменным, если перед этим были сделалы какие-то внешние вызовы.


E>Как мне кажется, довольно характерный пример псевдокода по работе о общими данными в многопоточных приложениях выглядит так:

E>
E>// Кто-то, что-то готовит.
E>lock();
E>...
E>flag = ready;
E>unlock();

E>// Кто-то, что-то ожидает.
E>while( true )
E>    lock();
E>    if( ready != flag )
E>        unlock();
E>    else
E>        ...
E>        ready = not_ready;
E>        unlock();
E>

E>Причем как раз доступ к общим данным (в данном случае, flag) производиться рядышком с использованием синхронизирующих примитивов.

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


Не обязательно. Компилятор может иметь список well-known функций, побочные эффекты от которых он знает. Например, фирме Майкрософт ничего не стоит научить VC++ оценивать побочные эффекты от вызова функций из API Win32. Технически, оптимизатор от VC++ содержит всё необходимое для этого.

E>Компиляторы не делают такой оптимизации сейчас.


И очень плохо. Дело в том, что вызов функций EnterCriticalSection/LeaveCriticalSection значим только для тех переменных, которые защищаются этой критической секцией. Т.е. барьер оптимизации, который при этом возникает, избыточен. По хорошему, в язык должны быть добавлены средства для явного указания границ оптимизации доступа к конкретной переменной.

Что-то типа.

CRITICAL_SECTION cs;
volatile int var1,var2,var3;

{
 ...
 
 EnterCriticalSection(&cs);

 locked(var1,var2,var3)
  {
   // var1,var2,var3 здесь перестают рассматриваться как volatile
  }

 LeaveCriticalSection(&cs);

 ...
}


E>И я сомневаюсь, что они будут делать ее в будущем.


Стандарт это не запрещает. Единственный 100% легальный метод гарантировать это на сегодня -- использовать volatile. Так что всё остальное -- на твой страх и риск.

E>Хотя бы из-за соображений совместимости.


Нет никаких сображений совместимости с нелегальным кодом. Полно примеров, когда новые компиляторы отказываются компилировать код, который компилировался старыми компиляторами, но не удовлетворял стандарту.

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


Пожалуйста. Но ты должен понимать, что делаешь таким образом платформенно-зависимый код.

E>И я не увидел пока реальных примеров из жизни, которые заставили бы меня это сделать. А было бы полезно увидеть (не только мне), если такие примеры имели место быть.
... << RSDN@Home 1.1.0 stable >>
В XXI век с CCore.
Копай Нео, копай -- летать научишься. © Matrix. Парадоксы
Re[6]: [2]: : volatile: а можно примеры?
От: Шахтер Интернет  
Дата: 19.01.05 00:20
Оценка:
Здравствуйте, MaximE, Вы писали:

ME>Шахтер wrote:


ME>[]


>> E>Предложение: давайте не превращать эту ветвь в очередное выяснение истины. Если есть примеры -- приводите, пожалуйста. Если нет, то будем считать это доказательством правильности позиции Максима

>>
>> Они уже приведены.

ME>Ok, я не прав был в семантике volatile, привел не удачный пример, и прогнал про sequence points.


ME>Мой поинт был в том (если этого до сих пор непонятно уважаемому Шахтеру), что какой бы семантикой не обладал volatile, ее просто не достаточно для multithreading,


Я это прекрасно знаю.

ME>и поэтому volatile бесполезен для multithreading.


Логическая ошибка. Недостаточно значит, необходимы дополнительные средства. Но это не значит -- не надо использовать.

ME>--

ME>Maxim Yegorushkin
... << RSDN@Home 1.1.0 stable >>
В XXI век с CCore.
Копай Нео, копай -- летать научишься. © Matrix. Парадоксы
Re[18]: volatile у переменной класса
От: emusic Франция https://software.muzychenko.net/ru
Дата: 19.01.05 03:32
Оценка:
Здравствуйте, achp, Вы писали:

E>>Я уже приводил код с указателями. В каждом потоке в каждый момент времени существует только один указатель на объект, по которому может производиться доступ. Следовательно, допустимо применить оптимизацию работы с указателями, задав компилятору режим No Aliasing.


A>Ну правильно, это же прямой обман компилятора. И вообще это чрезмерно агрессивная оптимизация, в общем случае недопустимая.


Аргументы, пожалуйста. И просьба прочитать в треде мои аргументы в пользу применения этих ключей оптимизации прежде, чем отвечать.
... << RSDN@Home 1.1.4 beta 3 rev. 185>>
Re[19]: volatile у переменной класса
От: emusic Франция https://software.muzychenko.net/ru
Дата: 19.01.05 04:02
Оценка: 20 (2) +1
Здравствуйте, achp, Вы писали:

A>Прохождение барьера всегда связано с вызовом внешней функции. Объект, к которому возможно обращение из нескольких потоков — либо глобальный, либо к нему ранее были созданы пути доступа, которые компилятор отследить не в силах. Следовательно, компилятор обязан предполагать возможность изменения данных объектов.


Я дважды приводил два примера. Один — со статическим переменными/функциями, обращения к которым компилятор легко может отследить и установить, что, извне ни одна переменная не изменяется. Что в данном случае может удержать компилятор от оптимизации работы с этими переменными, и заставить его предполагать, что после вызова какой-то там внешней функции локальные для модуля статические переменные вдруг изменятся?

Второй пример — с созданием динамического объекта, на который в каждый момент времени существует только один способный к разыменованию указатель. В рамках каждого потока, разумеется.

A>Разумеется, это не касается случая, когда включена форсированная оптимизация. Ну, это уже ваш собственный выбор — у компилятора к услугам обманщиков вообще есть широчайший ассортимент способов устроить неопределенное поведение.


Прошу показать мне место в описании ключей /Ow и /Oa компилятора MS VC++, где об этом говорится.

A>По мне так это несильно отличается от вот такого:


A>
A>int f()
A>{
A>    char const* const p = "aaa";
A>    *const_cast<char*>(p) = 'b';
A>    const_cast<char const*&>(p) = p + 1;
A>}
A>


Отличается принципиально. В силу того, что единственная языковая конструкция, применимая к multithreading — этот самый volatile. И почему-то компилятор, "обманутый" в моем примере ключом /Oa, при добавлении volatile к определению переменных вдруг начинает генерировать совершенно работоспособный код. Наверное, это случайность, да? А какие уточняющие спецификаторы нужно внести в вышеприведенный код, чтобы обманутый (уже без кавычек) компилятор сделал все правильно?

A>Если же барьер не обеспечивает синхронизации памяти между процессорами, — ну тут уж извиняйте — никакое volatile вам не поможит.


Разумеется. О чем я и говорил — что без volatile многопоточный код будет в общем случае некорректен, и все доводы противников volatile о том, что у них все работает опираются исключительно на совокупность частных случаев.

A>В Си/Си++ как языке просто нет легальных средств для такой тонкой оптимизации.


Не понял. Какие, по-Вашему, в Си/Си++ вообще есть "легальные средства для оптимизации"? Я не знаю ни одного В языке есть средства, которые могут помочь проводить оптимизацию, но и только. И которые с развитием техники оптимизации в компиляторах постепенно утрачивают значение — register давно стал бесполезен, арифметические операции ++/-- тоже давно перестали быть эффективнее прибавления/вычитания единицы.

Собственно, меня вообще удивляет, почему следующее утверждение кто-то не согласен считать аксиомой: "До тех пор, пока в языке C++ не появится средств для указания наличия многопоточности, компилятор имеет право на любую оптимизацию, при которой сохраняется правильное поведение программы в однопоточном варианте". Аргументированных возражений никто до сих пор не привел. Единственное, что в C/C++ хотя бы косвенно указывает на какую-то асинхронность — это volatile.
... << RSDN@Home 1.1.4 beta 3 rev. 185>>
Re[9]: volatile у переменной класса
От: emusic Франция https://software.muzychenko.net/ru
Дата: 19.01.05 05:07
Оценка:
Здравствуйте, MaximE, Вы писали:

ME>POSIX не требует volatile.


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

ME>Осталось разобраться для win32.


Кроме POSIX и Win32, в мире не существует больше платформ? В этом твоя главная ошибка — ты высказываешь общие утверждения, опираясь лишь на частные случаи. О том, что в POSIX достаточно барьеров, с тобой никто не спорил — это установлено спецификацией POSIX. Однако нет всеобщей спецификации, которая гарантировала бы достаточность разного рода средств синхронизации в отсутствие volatile.
... << RSDN@Home 1.1.4 beta 3 rev. 185>>
Re[7]: [2]: : volatile: а можно примеры?
От: MaximE Великобритания  
Дата: 19.01.05 06:06
Оценка:
Здравствуйте, Шахтер, Вы писали:

[]

ME>>Мой поинт был в том (если этого до сих пор непонятно уважаемому Шахтеру), что какой бы семантикой не обладал volatile, ее просто не достаточно для multithreading,


Ш>Я это прекрасно знаю.


ME>>и поэтому volatile бесполезен для multithreading.


Ш>Логическая ошибка. Недостаточно значит, необходимы дополнительные средства. Но это не значит -- не надо использовать.


Исправляю свою логическую ошибку — volotile не недостаточен, а иррелевантен.
Re[10]: volatile у переменной класса
От: MaximE Великобритания  
Дата: 19.01.05 06:20
Оценка:
Здравствуйте, emusic, Вы писали:

E>Здравствуйте, MaximE, Вы писали:


ME>>POSIX не требует volatile.


E>Это личные предпочтения POSIX. Не более того. POSIX — замкнутая система, спецификация которой охватывает и аппаратную часть, и саму программу, и окружение программы. Это позволяет ей налагать дополнительные ограничения на поведение компилятора — в частности, на оптимизацию.


Правилнее было бы сказать, что win32 — это закрытая система. POSIX — открытая, можешь разработать и внести свои предложения на рассмотрение. (например потребовать, чтоб volatile был нужен )

E>Однако даже POSIX-совместимый компилятор совершенно не обязан предполагать, что значение любой переменной может измениться после вызова любой внешней функции


Это так.

E> — к этому его обязывают лишь вызовы известных системных функций.


POSIX явно специфицирует какие функции являются барьерами.

ME>>Осталось разобраться для win32.


E>Кроме POSIX и Win32, в мире не существует больше платформ?


Я говорю про то, что я знаю. На мой взгляд, POSIX и win32 — самые распространенные. Если ты специалист в mac, dec или еще каких threads, можешь просветить.

E>В этом твоя главная ошибка — ты высказываешь общие утверждения, опираясь лишь на частные случаи. О том, что в POSIX достаточно барьеров, с тобой никто не спорил — это установлено спецификацией POSIX.


Для меня POSIX и win32 — это 100% случаев. Хочешь обсудить другие платформы — тебе никто не запрещает.

E>Однако нет всеобщей спецификации, которая гарантировала бы достаточность разного рода средств синхронизации в отсутствие volatile.


Еще раз: POSIX volatile не нужен. В MSDN я также не нашел упоминания, что им нужен volatile. Делаю вывод, что для win32 он также не нужен.
Re[11]: volatile у переменной класса
От: Odi$$ey Россия http://malgarr.blogspot.com/
Дата: 19.01.05 06:34
Оценка:
Здравствуйте, MaximE, Вы писали:

ME>В MSDN я также не нашел упоминания, что им нужен volatile. Делаю вывод, что для win32 он также не нужен.


Re: volatile у переменной класса
Автор: c-smile
Дата: 10.01.05
Re[12]: [2]: : volatile: а можно примеры?
От: Andrew S Россия http://alchemy-lab.com
Дата: 19.01.05 06:44
Оценка: 18 (1) +1
>> (x) Случай Vx,Ax. Может ли в этом случае компилятор закэшировать значение переменной? Имеются в виду как обычные, так и наиболее агрессивные настройки оптимизации.
>> Итого, соотв, 4 варианта.

ME>Не будет закэшировано во всех вариантах. (если, конечно, никто не применит ключ компиляции "компайлер, здесь нет никакого альясинга, мамой клянусь!")


Заметьте, я говорил как про обычную, так и агрессивную оптимизацию. Итак, вы все-таки признаете, что при включенной агрессивной оптимизации возможны проблемы. Например, вычисление значение переменной заранее, и затем использование его после внешнего изменения этого значения (пример, кстати, вам привел emusic). В случае с простыми interlocked, это, конечно, довольно сложно представить (но наверняка придумать пример можно), но как только в дело вступают критические секции, которые никак не позиционируют себя по отношению к объекту, который охраняют, ситуация усложняется.

Тогда немного переформулируем вопрос. При условии того, что для синхронизации используются стандартные функции\примитивы синхронизации, предоставляемые ОС, использование volatile в определении разделяемой переменной:

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

Соответственно, выбрать можно любой из пунктов (или несколько сразу) + придумать свои вариант, ессно, обосновав ответ.
Для себя я, как уже говорил, выбираю б), поскольку не вижу минусов при указании подобным переменным спецификатора volatile. Оптимизировать доступ к ним обычно и не требуется, а плюсы, хоть редко, но быть могут, как уже было показано. С вариантом с) я никогда не встречался.
http://www.rusyaz.ru/pr — стараемся писАть по-русски
Re[11]: volatile у переменной класса
От: emusic Франция https://software.muzychenko.net/ru
Дата: 19.01.05 07:08
Оценка: 16 (1)
Здравствуйте, MaximE, Вы писали:

E>>POSIX — замкнутая система, спецификация которой охватывает и аппаратную часть, и саму программу, и окружение программы.


ME>Правилнее было бы сказать, что win32 — это закрытая система. POSIX — открытая, можешь разработать и внести свои предложения на рассмотрение.


POSIX — не закрытая, а замкнутая система. Это означает, что спецификация платформы, кроме аппаратных особенностей и программной среды, включает еще и требования к языку, в данном случае — C/C++. Чтобы соответствовать спецификации POSIX, компилятор обязан обеспечить условия взаимной видимости переменных в pthreads. Однако это вовсе не обязывает его обеспечивать их в случае организации параллелизма иными, нежели pthreads, способами. Намек понятен?

ME>Я говорю про то, что я знаю.


Нет, изначально ты высказывал именно всеобщие утверждения о "бесполезности и даже вредности" volatile. И лишь после того, как тебя приперли к стенке, ты начал ссылаться на POSIX — опять-таки распространяя эту частную (пусть и популярную) систему на все случаи жизни.

ME> На мой взгляд, POSIX и win32 — самые распространенные. Если ты специалист в mac, dec или еще каких threads, можешь просветить.


Да дело же не в конкретных платформах и не в конкретных же реализациях многопоточности. А в том, что, если мы хотим обеспечить максимальную переносимость кода — мы обязаны изначально снабдить каждую разделямую переменную спецификатором volatile — кроме тех переменных, которые везде и явно модифицируются специальными внешними функциями, вроде InterlockedXXX. Это минимум. Далее, в зависимости от платформы, нам придется либо ужесточать условия, добавляя к имеющемуся volatile примитивы типа критических секций и/или барьеров, либо ослаблять их, заменяя volatile на средства, гарантирующие на данной платформе взаимную видимость переменных.

ME>Для меня POSIX и win32 — это 100% случаев.


Это для тебя. Для кого-то, кроме BC 3.1 for DOS, ничего другого не существует Если уж на то пошло, то в оригинальном сообщении автор спрашивал, "есть ли необходимость делать разделяемую переменную volatile", а не "достаточно ли будет одного volatile" для нормальной работы. И ссылался при этом на Рихтера, из чего можно было сделать вывод, что он работает под Win32. А ты ему с места в карьер принялся доказывать "бесполезность и вредность" volatile, да еще и со ссылками на POSIX впоследствии

ME>Еще раз: POSIX volatile не нужен. В MSDN я также не нашел упоминания, что им нужен volatile.


То есть, тебе требуется именно явное указание на его нужность? Оговорки насчет "concurrently executing thread" в описании самого спецификатора volatile тебе недостаточно? Мда, тяжелый случай.
... << RSDN@Home 1.1.4 beta 3 rev. 185>>
Re[12]: volatile у переменной класса
От: MaximE Великобритания  
Дата: 19.01.05 08:11
Оценка:
Здравствуйте, Odi$$ey, Вы писали:

OE>Здравствуйте, MaximE, Вы писали:


ME>>В MSDN я также не нашел упоминания, что им нужен volatile. Делаю вывод, что для win32 он также не нужен.


OE>Re: volatile у переменной класса
Автор: c-smile
Дата: 10.01.05


Это единственное упоминание volatile и multithreading в MSDN. (там еще есть куски threaded кода с volatile).

Первое, цитита относится к секции MSDN C/C++ Languages, где MS ошибочно пытается своими словами трактовать стандарт вообще, и ключевое слово volatile в частности.

Второе, нигде в секции MSDN DLLs, Processes and Threads не упоминается о том, что shared variables должны быть volatile. Из этого следует, что это не является необходимым для win32 threading model. Логично также предположить, что если бы это действительно было необходимым, об этом было бы явно там написано (тем более что это официальная док-ция).
Re[7]: [2]: : volatile: а можно примеры?
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 19.01.05 08:42
Оценка: 30 (1) +1
Здравствуйте, Шахтер, Вы писали:

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


Ш>Не обязательно. Компилятор может иметь список well-known функций, побочные эффекты от которых он знает. Например, фирме Майкрософт ничего не стоит научить VC++ оценивать побочные эффекты от вызова функций из API Win32. Технически, оптимизатор от VC++ содержит всё необходимое для этого.


Как раз таки тогда VC++ прекрасно поймет, что после вызова функций типа WaitFor*Object нужно осуществлять перечитывание значений переменных, т.к. эти функции явно могут приводить к возникновению побочных эффектов.

E>>И я сомневаюсь, что они будут делать ее в будущем.


Ш>Стандарт это не запрещает. Единственный 100% легальный метод гарантировать это на сегодня -- использовать volatile. Так что всё остальное -- на твой страх и риск.


Вот здесь: Double-Checked Locking, Threads, Compiler Optimizations, and More Скот Мейерс показывает, что даже использование volatile не гарантирует ожидаемого эффекта в многопоточном приложении (даже при использовании примитивов синхронизации). И делает замечательный вывод:

Bottom line: the road to thread-safe code isn't paved with volatile


Ничего личного, Шахтер, но я более склонен согласиться с Мейерсом, чем с вами

Ш>Нет никаких сображений совместимости с нелегальным кодом. Полно примеров, когда новые компиляторы отказываются компилировать код, который компилировался старыми компиляторами, но не удовлетворял стандарту.


Думаю, что здесь не все так однозначно. Нынешний стандарт никак не определял особенностей и привязки к многопоточности. Что оставляло большое поле для реализации различных решений при создании многопоточных приложений. И отмахнуться от того, что 20% (цифра с потолка) написанных на C++ многопоточных приложений окажутся не совместимыми со следующим стандартом сейчас уже никто не сможет. А я подозреваю, что таких приложений гораздо больше.

Поэтому я надеюсь, может быть, напрасно, что добавление в C++ стандарт поддержки многопоточности произойдет без необходимости использования модификатора volatile для всех разделяемых между потоками данных.
... << RSDN@Home 1.1.4 beta 3 rev. 185>>


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[7]: Реальный пример использования volatile
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 19.01.05 08:42
Оценка:
Здравствуйте, What, Вы писали:

E>>Если бы код был POSIX-зависимым, или boost-зависимым, или ACE-зависимым, или commoncpp-зависимым, или glib-зависимым, или Win32-EnterCriticalSection/LeaveCriticalSection-зависимым, то volatile не была бы частью этой зависимости.

W>Как сказать... ACE и boost используют volatile в своей реализации.

Они в своей реализации могут использовать все, что им понравиться, лишь бы работало. Но они не требуют, чтобы мои данные были volatile
... << RSDN@Home 1.1.4 beta 3 rev. 185>>


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[12]: volatile у переменной класса
От: MaximE Великобритания  
Дата: 19.01.05 09:01
Оценка:
emusic wrote:

> Здравствуйте, MaximE, Вы писали:

>
> E>>POSIX — замкнутая система, спецификация которой охватывает и аппаратную часть, и саму программу, и окружение программы.
>
> ME>Правилнее было бы сказать, что win32 — это закрытая система. POSIX — открытая, можешь разработать и внести свои предложения на рассмотрение.
>
> POSIX — не закрытая, а замкнутая система. Это означает, что спецификация платформы, кроме аппаратных особенностей и программной среды, включает еще и требования к языку, в данном случае — C/C++. Чтобы соответствовать спецификации POSIX, компилятор обязан обеспечить условия взаимной видимости переменных в pthreads. Однако это вовсе не обязывает его обеспечивать их в случае организации параллелизма иными, нежели pthreads, способами. Намек понятен?

Компилятор должен поддерживать многопоточность — это раз. Семантика volatile — implementation defined — это два.

Никакой стандарт не гарантирует, что volatile вставит load инструкцию, но док-ции к (некоторым) компиляторам это гарантируют (чти и есть implementation defined). Но это еще пол дела.

Во-первых, load инструкция, в-общем, не гарантирует загрузку актуального значения из памяти без использование барьеров памяти. Во-вторых, платформа должна поддерживать атомарную загрузку/сохранение переменной, помеченной как volatile, также эта переменная должна быть выровнена в соответствии с требованиями той атомарной инструкции, иначе из-за явления word tearing вся атомарность инструкции сойдет на нет.

Есть тип, который гарантирует атомарность load и store на конкретной платформы для переменной этого типа — это sig_atomic_t. Только, почему-то, нет типа thread_atomic_t.

> ME>Я говорю про то, что я знаю.

>
> Нет, изначально ты высказывал именно всеобщие утверждения о "бесполезности и даже вредности" volatile. И лишь после того, как тебя приперли к стенке, ты начал ссылаться на POSIX — опять-таки распространяя эту частную (пусть и популярную) систему на все случаи жизни.

И сейчас утверждаю, что volatile бесполезен и вреден для multithreading.

Одно из применений multithreading — получить максимальное быстродействие, задействовав все процессоры системы. С другой стороны, volatile variables связывают руки оптимизатору. Звучит глупо: хочешь добиться максимального быстродействия, но запрещаешь оптимизацию.

Компилятор, который бы требовал применение volatile к thread shared variables для конкретной платформы по этой причине попросту бы там не продавался. В опровержение моих слов назови хоть один такой компилятор.

> ME> На мой взгляд, POSIX и win32 — самые распространенные. Если ты специалист в mac, dec или еще каких threads, можешь просветить.

>
> Да дело же не в конкретных платформах и не в конкретных же реализациях многопоточности. А в том, что, если мы хотим обеспечить максимальную переносимость кода — мы обязаны изначально снабдить каждую разделямую переменную спецификатором volatile ...

Это твои выдумки. Приведи пункт стандарта или соответсвующий текст из reference manual к какой либо threading model (кроме java, конечно, где volatile имеет совсем другую семантику).

[]


> ME>Для меня POSIX и win32 — это 100% случаев.

>
> Это для тебя. Для кого-то, кроме BC 3.1 for DOS, ничего другого не существует Если уж на то пошло, то в оригинальном сообщении автор спрашивал, "есть ли необходимость делать разделяемую переменную volatile", а не "достаточно ли будет одного volatile" для нормальной работы. И ссылался при этом на Рихтера, из чего можно было сделать вывод, что он работает под Win32. А ты ему с места в карьер принялся доказывать "бесполезность и вредность" volatile, да еще и со ссылками на POSIX впоследствии

Если бы он завтра это еще раз написал, я бы ему еще раз так и ответил.

> ME>Еще раз: POSIX volatile не нужен. В MSDN я также не нашел упоминания, что им нужен volatile.

>
> То есть, тебе требуется именно явное указание на его нужность? Оговорки насчет "concurrently executing thread" в описании самого спецификатора volatile тебе недостаточно? Мда, тяжелый случай.

Эта оговорка, а лучше сказать ошибка, сидит в секции C/C++ Language Reference с незапамятных времен. Как умеют люди из mictrosoft трактовать C++ стандарт и писать код на C++ мы все тут знаем.

Скачай Platform SDK, и найди в его документации упоминание о том, что thread shared variables должны быть volatile.

--
Maxim Yegorushkin
Posted via RSDN NNTP Server 1.9
Re[13]: volatile у переменной класса
От: emusic Франция https://software.muzychenko.net/ru
Дата: 19.01.05 11:43
Оценка:
Здравствуйте, MaximE, Вы писали:

ME>Это единственное упоминание volatile и multithreading в MSDN.


Нет, это единственное упоминание, найденное тобой Ибо авторы MSDN не предполагали, что ты станешь искать непременно по слову multithreading. Поищи по thread или concurrent.

Еще про volatile есть статейка 324866 (a variable in the kernel that is used to manage the list of pending-event notifications was not declared as volatile).

Кстати, в VC++ 7 появилась intrinsic-функция _ReadWriteBarrier. Это как раз случай барьера на уровне компилятора — в отличие от барьера на уровне аппаратуры.

ME>Второе, нигде в секции MSDN DLLs, Processes and Threads не упоминается о том, что shared variables должны быть volatile.


Опять-таки — с чего ты взял, что об этом должно упоминаться непременно в указанной секции? Если тебе удобно там это искать — MSDN-то при чем? А о том, что volatile может потребоваться для разделяемых данных, раз десять упомянуто в секциях описания языка, где идет речь об определениях переменных, квалификаторах, указателях и т.п. По-моему, вполне резонно предполагать, что перед изучением Win API программист хотя бы в общих чертах ознакомится с языком вообще.

Еще к VC++ 2.0 была статейка 120926:
If the value of a variable can be modified by another thread or by the operating system and your program depends on this behavior, you should declare the variable as volatile. Without the volatile keyword, the optimizing compiler may enregister a copy of this variable, leading to unexpected behavior.

ME> Из этого следует, что это не является необходимым для win32 threading model.


Если бы секция "DLLs, processes and threads" являлась исчерпывающей документацией по программированию многопоточных приложений на C/C++ под Win32 — тогда следовало бы.

ME> Логично также предположить, что если бы это действительно было необходимым, об этом было бы явно там написано (тем более что это официальная док-ция).


Оно явно и написано. Во многих местах, на разные лады. Если кому-то угодно читать лишь выборочно — это его личные трудности
... << RSDN@Home 1.1.4 beta 3 rev. 185>>
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.