Нужны ли тут кртические секции?
От: CFA Россия  
Дата: 27.10.11 09:57
Оценка:
Есть многопоточное приложение. Под windows на delphi, но думаю это не важно.
Есть ряд глобальных переменных которые могут читать/менять вспомогательные потоки, основной поток их только читает.
Со сложными переменными вроде массивов, записей, объектов все понятно, и критические секции решительно нужны.
А переменные простых типов — Integer/Word/Byte/etc — нужно ли оборачивать их чтение во вход/выход из КС?
С одной стороны логика подсказывает, что чтение и запись должны быть атомарны, тк это одна инструкция CPU, но в современных реалиях, у почти любого процессора есть несколько ядер, не случится ли ситуация когда 2 потока пишут в одну переменную практически одновременно, и в переменной будут записаны старшие байты из одного потока, а младшие из другого?
С точки зрения приложения совсем не важно, какой именно поток запишет данные, важно чтоб они были целостными.
Я пишу — по ночам больше тем.
Re: Нужны ли тут кртические секции?
От: acDev Россия  
Дата: 27.10.11 10:09
Оценка: +1 -1
Здравствуйте, CFA, Вы писали:

CFA>Есть многопоточное приложение. Под windows на delphi, но думаю это не важно.

CFA>Есть ряд глобальных переменных которые могут читать/менять вспомогательные потоки, основной поток их только читает.
CFA>Со сложными переменными вроде массивов, записей, объектов все понятно, и критические секции решительно нужны.
CFA>А переменные простых типов — Integer/Word/Byte/etc — нужно ли оборачивать их чтение во вход/выход из КС?

Если изменяемое значение является счётчиком (или подобным), то без Interlocked* функций не обойтись!
А если у вас просто флаговое предназначение "слова", то достаточно просто выровнять "слово" на 4 байт, что бы обеспечить атомарность.
Re[2]: Нужны ли тут кртические секции?
От: CFA Россия  
Дата: 27.10.11 10:21
Оценка:
Здравствуйте, acDev, Вы писали:

D>Если изменяемое значение является счётчиком (или подобным), то без Interlocked* функций не обойтись!

D>А если у вас просто флаговое предназначение "слова", то достаточно просто выровнять "слово" на 4 байт, что бы обеспечить атомарность.

Не это не счетчик, но и не флаг — а некоторое число, которое будет использоваться в вычислениях основным потоком. Когда любой из потоков его меняет, он не опирается на предыдущее значение. Таким образом не важно, кто записал, важно чтоб число было в точности таким, какое записывал один из потоков, а не "каша" из них.
Получается, если слово не выровнено на 4 байта, то может произойти такая ситуация, когда действительно половина слова записана одним потоком, а вторая половина другим? Полагаю, что пруфы надо искать где-то на сайте интела/амд? Если знаете, был бы признателен за ссылку на оные.
Я пишу — по ночам больше тем.
Re[2]: Нужны ли тут кртические секции?
От: ДимДимыч Украина http://klug.org.ua
Дата: 27.10.11 10:27
Оценка: -1
Здравствуйте, acDev, Вы писали:

D>А если у вас просто флаговое предназначение "слова", то достаточно просто выровнять "слово" на 4 байт, что бы обеспечить атомарность.


И получить проблемы на SMP с раздельными кэшами данных.
Обязательно бахнем! И не раз. Весь мир в труху! Но потом. (ДМБ)
Re: Нужны ли тут кртические секции?
От: okman Беларусь https://searchinform.ru/
Дата: 27.10.11 11:14
Оценка: +1
Здравствуйте, CFA, Вы писали:

CFA>Есть многопоточное приложение. Под windows на delphi, но думаю это не важно.

CFA>Есть ряд глобальных переменных которые могут читать/менять вспомогательные потоки, основной поток их только читает.
CFA>Со сложными переменными вроде массивов, записей, объектов все понятно, и критические секции решительно нужны.
CFA>А переменные простых типов — Integer/Word/Byte/etc — нужно ли оборачивать их чтение во вход/выход из КС?
CFA>С одной стороны логика подсказывает, что чтение и запись должны быть атомарны, тк это одна инструкция CPU, но в современных реалиях, у почти любого процессора есть несколько ядер, не случится ли ситуация когда 2 потока пишут в одну переменную практически одновременно, и в переменной будут записаны старшие байты из одного потока, а младшие из другого?
CFA>С точки зрения приложения совсем не важно, какой именно поток запишет данные, важно чтоб они были целостными.

Оборачивать такие переменные в CS не нужно.
Достаточно обеспечить условие, чтобы они, во-первых, были корректно выравненными, а во-вторых,
исключить влияние на них компилятора. Это называется агрессивная оптимизация — без должной подсказки
компилятор может "разобраться" с такой переменной очень своеобразно (держать ее значение в регистре, а
кое-где вообще выкинуть за борт), из-за чего разные потоки будут видеть значение этой переменной по-разному.
В C++ для этой цели существует ключевое слово volatile, но как с этим обстоят дела в Delphi — не в курсе.

Вот где действительно требуется синхронизация — это операции инкремента/декремента и обмена.
Для этих целей в семействе Win32 API специально разработаны Interlocked-функции.
Еще очень советую разобраться с темой "memory reordering" — на x86 эта тема очень
популярна и иногда откидывает ну очень занятные коленца.

Информацию, как всегда, ищите в мануалах на сайте Intel — их можно загружать совершенно свободно.
К огорчению, видимо, для Вас — большая часть информации по системному и низкоуровневому программированию,
как правило, подается в свете C/C++.
Re[3]: 2 Jolly Roger
От: ДимДимыч Украина http://klug.org.ua
Дата: 27.10.11 15:05
Оценка:
ДД>И получить проблемы на SMP с раздельными кэшами данных.

уточню: без аппаратной поддержки когерентности.

Если все равно не согласны, обоснуйте плз.
Обязательно бахнем! И не раз. Весь мир в труху! Но потом. (ДМБ)
Re[4]: 2 Jolly Roger
От: Аноним  
Дата: 27.10.11 15:12
Оценка:
ДД>>И получить проблемы на SMP с раздельными кэшами данных.
ДД>уточню: без аппаратной поддержки когерентности.
ДД>Если все равно не согласны, обоснуйте плз.

Какие могут быть проблемы? Автор же сказал, что его не волнует, что данные будут не когеренты, его волнует только чтобы они были валидны. Вот если данные представляют собой, скажем счетчик — тогда нужны барьеры.
Re[5]: 2 Jolly Roger
От: ДимДимыч Украина http://klug.org.ua
Дата: 27.10.11 15:21
Оценка: 1 (1)
Здравствуйте, Аноним, Вы писали:

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


Если, например, модификация и чтение происходит в цикле без барьеров:
while (!quit)
{
   global_variable = <какие-то вычисления>;
   ...
}

то изменение global_variable в одной нити может вообще не дойти до другой нити, даже если она volatile.
Обязательно бахнем! И не раз. Весь мир в труху! Но потом. (ДМБ)
Re[4]: 2 Jolly Roger
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 27.10.11 16:35
Оценка:
Здравствуйте, ДимДимыч, Вы писали:

ДД>>И получить проблемы на SMP с раздельными кэшами данных.

ДД>уточню: без аппаратной поддержки когерентности.

А такое бывает, кроме как в безвременно почившем IA64?
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[4]: 2 Jolly Roger
От: Jolly Roger  
Дата: 27.10.11 16:55
Оценка:
Здравствуйте, ДимДимыч, Вы писали:

ДД>>И получить проблемы на SMP с раздельными кэшами данных.


ДД>уточню: без аппаратной поддержки когерентности.


Сферический конь в вакууме?

ДД>Если все равно не согласны, обоснуйте плз.


Если у процессора нет автоподдержки когерентности, то должен быть механизм ручного её обеспечения с соответствующей поддержкой компилятором. Но это всё равно чистые фантазии, не связанные с реальностью
"Нормальные герои всегда идут в обход!"
Re[5]: 2 Jolly Roger
От: Jolly Roger  
Дата: 27.10.11 16:57
Оценка:
Здравствуйте, Евгений Музыченко, Вы писали:

ЕМ>Здравствуйте, ДимДимыч, Вы писали:


ДД>>>И получить проблемы на SMP с раздельными кэшами данных.

ДД>>уточню: без аппаратной поддержки когерентности.

ЕМ>А такое бывает, кроме как в безвременно почившем IA64?


Хм, в Itanium аппаратная поддержка когерентность была, ЕМНИП.
"Нормальные герои всегда идут в обход!"
Re[6]: 2 Jolly Roger
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 27.10.11 17:17
Оценка:
Здравствуйте, Jolly Roger, Вы писали:

ЕМ>>А такое бывает, кроме как в безвременно почившем IA64?


JR>Хм, в Itanium аппаратная поддержка когерентность была, ЕМНИП.


Так это IA64 и есть.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[7]: 2 Jolly Roger
От: Jolly Roger  
Дата: 28.10.11 05:08
Оценка:
Здравствуйте, Евгений Музыченко, Вы писали:

ЕМ>Здравствуйте, Jolly Roger, Вы писали:


ЕМ>>>А такое бывает, кроме как в безвременно почившем IA64?


JR>>Хм, в Itanium аппаратная поддержка когерентность была, ЕМНИП.


ЕМ>Так это IA64 и есть.


Дык и я про то-же
"Нормальные герои всегда идут в обход!"
Re[5]: 2 Jolly Roger
От: ДимДимыч Украина http://klug.org.ua
Дата: 28.10.11 09:58
Оценка:
Здравствуйте, Jolly Roger, Вы писали:

ДД>>>И получить проблемы на SMP с раздельными кэшами данных.

ДД>>уточню: без аппаратной поддержки когерентности.

JR>Сферический конь в вакууме?


Как-то пришлось вылавливать баги после портирования системы на один из broadcom'овских MIPS'ов. На синхронизации решили сэкономить, volatile вместо мютексов

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


Memory barrier в примитивах синхронизации это и обеспечивает.

JR>Но это всё равно чистые фантазии, не связанные с реальностью


Согласен, маловероятно, что выпустят что-то из x86 с некогеретными кэшами. Но прикладные приложения, имхо, лучше сразу семантически корректно, без оглядки на аппаратные особенности
Обязательно бахнем! И не раз. Весь мир в труху! Но потом. (ДМБ)
Re[6]: 2 Jolly Roger
От: Jolly Roger  
Дата: 28.10.11 13:28
Оценка:
Здравствуйте, ДимДимыч, Вы писали:

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


ДД>>>>И получить проблемы на SMP с раздельными кэшами данных.

ДД>>>уточню: без аппаратной поддержки когерентности.

JR>>Сферический конь в вакууме?


ДД>Как-то пришлось вылавливать баги после портирования системы на один из broadcom'овских MIPS'ов. На синхронизации решили сэкономить, volatile вместо мютексов


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


ДД>Memory barrier в примитивах синхронизации это и обеспечивает.


Ну вообще-то мьютексы, volatile и memory barrier в общем случае несут разную, непересекающуюся семантическую нагрузку, выполняют разные задачи. Мьютексы обеспечивают однопоточную работу участка кода, volatile защищают от агрессивной оптимизации, memory barrier борется с реордерингом. Но разумеется, конкретная наполненость зависит от компилятора и, опосредованно, от процессора.

JR>>Но это всё равно чистые фантазии, не связанные с реальностью


ДД>Согласен, маловероятно, что выпустят что-то из x86 с некогеретными кэшами. Но прикладные приложения, имхо, лучше сразу семантически корректно, без оглядки на аппаратные особенности


Так-то оно так, только это может очень дорого обойтись в части производительности
"Нормальные герои всегда идут в обход!"
Re: Нужны ли тут кртические секции?
От: Pzz Россия https://github.com/alexpevzner
Дата: 29.10.11 19:02
Оценка:
Здравствуйте, CFA, Вы писали:

CFA>С одной стороны логика подсказывает, что чтение и запись должны быть атомарны, тк это одна инструкция CPU, но в современных реалиях, у почти любого процессора есть несколько ядер, не случится ли ситуация когда 2 потока пишут в одну переменную практически одновременно, и в переменной будут записаны старшие байты из одного потока, а младшие из другого?


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