Многопоточность в C++
От: plusovik  
Дата: 19.05.25 09:16
Оценка:
Здравствуйте.
Основные механизмы многопоточности, с которыми я сталкивался, это mutex и atomic. У atomic есть аргументы, предназначенные для упорядочивания доступа к памяти, которые в некоторых библиотечных функциях обычно задаются по умолчанию.

memory_order_seq_cst – указывает на sequential consistent модель
memory_order_acquire, memory_order_release, memory_order_acq_rel, memory_order_consume – относятся к модели, основанной на acquire/release семантике
memory_order_relaxed – указывает на relaxed-модель

Также есть барьеры. Часто ли перечисленные аргументы и барьеры нужны на практике в тех проектах, где используется многопоточность или их необходимо знать в редких узкоспециализированных областях? Если в редких узкоспециализированных, то в каких именно? Правильно ли я понимаю, что механизмы упорядочивания памяти и барьеры служат для написания кода, свободного не только от блокировок, но и от ожиданий?
Re: Многопоточность в C++
От: Великий Мессия google
Дата: 19.05.25 10:20
Оценка:
memory_order_consume депрекейтет

ну вот есть std::shared_ptr
там используется std::atomic с параметрами
насколько он там нужен?
может можно обойтись без него?
на эти и другие вопросы есть множество видео докладов и лекций
не ленитесь
идите ищите читайте-смотрите
Re: Многопоточность в C++
От: Videoman Россия https://hts.tv/
Дата: 19.05.25 14:08
Оценка:
Здравствуйте, plusovik, Вы писали:

P>Также есть барьеры. Часто ли перечисленные аргументы и барьеры нужны на практике в тех проектах, где используется многопоточность или их необходимо знать в редких узкоспециализированных областях?

Часто/редко зависит от уровня на котором решаются задачи. Если ты пишешь библиотечные многопоточные примитивы, то часто. Если ты пишешь прикладной код, то может быть и редко.

P>Если в редких узкоспециализированных, то в каких именно?

Собственные многопоточные примитивы.

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

Перпендикулярно! Сами примитивы, такие как std::mutex и std::condition_variable внутри вовсю используют упорядочивание и барьеры.
Re: Многопоточность в C++
От: Chorkov Россия  
Дата: 20.05.25 08:48
Оценка:
Здравствуйте, plusovik, Вы писали:

P>Также есть барьеры. Часто ли перечисленные аргументы и барьеры нужны на практике в тех проектах, где используется многопоточность или их необходимо знать в редких узкоспециализированных областях? Если в редких узкоспециализированных, то в каких именно?


Барьеры и атомики — самые низкоуровневые примитивы. Ниже только ассемблер.
Они вам понадобятся при написании собственных примитивов синхронизации (очередь сообщений, например) и/или если захотите вложиться в оптимизацию.
Это связанные задачи, потому что при написании библиотечного, кода сценарий использования заранее неизвестен, парадигма "не пессимизировать" обязывает вас оптимизировать код на низком уровне.

Но на уровне клиентского кода, их использование — редкость.
Чаще встрчаются очереди сообщений, std::asyn/std::future, OpenMP, tbb, mpi и т.д.

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


Формально, нет, это ортогонально. Свобода от блокировок/ожиданий обеспечивается скорее алгоритмом. Например, waint-free очередь сообщений можно написать и на атомиках, и на мутексах (используя большое число мутексов и try_lock).
Но на практике, все сводится к использованию waint-free/lock-free контейнеров. А эти контейнеры пишутся как библиотечный код (см. выше).
Re: Многопоточность в C++
От: tapatoon  
Дата: 20.05.25 08:52
Оценка: :)
Здравствуйте, plusovik, Вы писали:

P>Также есть барьеры. Часто ли перечисленные аргументы и барьеры нужны на практике в тех проектах, где используется многопоточность или их необходимо знать в редких узкоспециализированных областях?

За 20+ лет прикладного программирования на плюсах под винду memory_order и барьеры не понадобились
Центр ИПсО Сил Специальных Операций
Re: Многопоточность в C++
От: okman Беларусь https://searchinform.ru/
Дата: 21.05.25 13:34
Оценка:
Здравствуйте, plusovik, Вы писали:

P>...

P>Также есть барьеры. Часто ли перечисленные аргументы и барьеры нужны на практике в тех проектах, где используется многопоточность или их необходимо знать в редких узкоспециализированных областях? Если в редких узкоспециализированных, то в каких именно?

Можно считать, что эти вещи достаточно низкоуровневые и реальная необходимость в их использовании возникает редко.

Иногда может потребоваться написать что-нибудь "этакое", где популярные библиотечные средства не подходят. Ну например, пусть это будет какая-то своя система подсчета ссылок в стиле shared_ptr.

И вот, дойдя до атомарной работы со счетчиком, ты такой открываешь исходники какого-нибудь std::shared_ptr или boost::shared_ptr, чтобы подсмотреть, как это сделано у "больших умных дядечек". И видишь такое:
long operator++()
{
    return value_.fetch_add( 1, std::memory_order_acq_rel ) + 1;
}

long operator--()
{
    return value_.fetch_sub( 1, std::memory_order_acq_rel ) - 1;
}


И начинаешь задумываться: а почему здесь 'acq_rel', а не 'seq_cst', например? На что это влияет?
Открыв аналогичные исходники MSVC, с удивлением там встречаешь relaxed-инкремент (для ARM).

И вот здесь начинается разница между "все так делают, сделаю и я" и "хочу знать, почему так, а не иначе; хочу 100% разобраться". Барьеры и модели памяти — это очень сложная и глубокая тема. Если удастся понять, как это устроено и по каким правилам все работает — получишь массу удовольствия.

Также очень рекомендую, когда полученные знания более-менее улягутся в голове, посмотреть вот эти видео от Г. Саттера:

C++ and Beyond 2012: Herb Sutter — atomic Weapons (1 и 2 части)
https://www.youtube.com/watch?v=A8eCGOqgvH4
https://www.youtube.com/watch?v=KeLBd2EJLOU

(не уверен на счет блокировок youtube; но наверняка видео по названиям можно найти на других ресурсах).
Re[2]: Многопоточность в C++
От: _NN_  
Дата: 05.06.25 13:53
Оценка:
Здравствуйте, okman, Вы писали:

O>C++ and Beyond 2012: Herb Sutter — atomic Weapons (1 и 2 части)

Могу ещё и различные видео Федора посоветовать:
CppCon 2017: Fedor Pikus “C++ atomics, from basic to advanced. What do they really do?”
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re: Многопоточность в C++
От: mukos СССР  
Дата: 03.07.25 18:03
Оценка:
Здравствуйте, plusovik, Вы писали:

P>memory_order_seq_cst – указывает на sequential consistent модель

P>memory_order_acquire, memory_order_release, memory_order_acq_rel, memory_order_consume – относятся к модели, основанной на acquire/release семантике
P>memory_order_relaxed – указывает на relaxed-модель

я не очень спец, для меня барьеры не то чтобы открытая книга, но мое скудное понимание такое

memory_order_relaxed — самый простой — это когда синхронизируются данные сами по себе — например int который хранит значение, и НЕЗАВИСИМ от других данных и просто нужна атомарность
memory_order_acquire — для флага что некоторые данные должны быть прочитаны в допустим контейнере ( это гарантирует что запись в контейнер закончена )
memory_order_release — тоже самое что и предыдущий — но только как флаг для записи (или допустим head lock free stack как часть контейнера) ... поэтому они в основном парные

memory_order_consume — вообще тема для какого-то мутного процессора

вроде так, поправьте если не прав
Отредактировано 03.07.2025 18:05 пассажир . Предыдущая версия .
Re: Многопоточность в C++
От: Pzz Россия https://github.com/alexpevzner
Дата: 03.07.25 19:31
Оценка:
Здравствуйте, plusovik, Вы писали:

P>Также есть барьеры. Часто ли перечисленные аргументы и барьеры нужны на практике в тех проектах, где используется многопоточность или их необходимо знать в редких узкоспециализированных областях? Если в редких узкоспециализированных, то в каких именно? Правильно ли я понимаю, что механизмы упорядочивания памяти и барьеры служат для написания кода, свободного не только от блокировок, но и от ожиданий?


Очень зависит от конкретного случая. Причём не от его "высокоуровневости" а от того, что по существу происходит в этом коде.

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

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

Да, ну и если перепутать acquire/release, то тут уж не только производительность, но и корректность может пострадать.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.