powered by simpleCommunicator - 2.0.59     © 2025 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / C++ [игнор отключен] [закрыт для гостей] / Какую библиотеку посоветуете с потокобезопасными контейнерами?
25 сообщений из 82, страница 2 из 4
Какую библиотеку посоветуете с потокобезопасными контейнерами?
    #39420469
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
AlekseySQLЯ наоборот хочу поставить очень низкий приоритет своим потокам. Таким образом мне удастся запустить 4 дочерних потока (по количеству ядер) + основной поток для показа текущих сообщений из дочерних. Причем в этом случае основной поток не будет тормозить, потому что у него относительно дочерних потоков будет высокий приоритет и в тоже время ядро не будет простаивать между показами информации о ходе работы.
Средствами ОС внутри потока понижай приоритет, по завершению возвращай как было. Не надо никаких менеджеров самодельных городить.
Для виндовса GetCurrentThread() и SetThreadPriority()
...
Рейтинг: 0 / 0
Какую библиотеку посоветуете с потокобезопасными контейнерами?
    #39420668
Фотография Anatoly Moskovsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
CEMbА если правильный, но opensource/freeware?
Вы думаете за это не платят? Думаете, миллионы строк кода в ядре линукса написаны людьми которые не получают зарплату, просто как хобби?
...
Рейтинг: 0 / 0
Какую библиотеку посоветуете с потокобезопасными контейнерами?
    #39420851
khizmax
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Привет,
я тот самый дядька, который гонит пургу на стендапах :-) Не мог пройти мимо

NekZНапример, что не нужно математически доказывать корректность алгоритма -- нужно его обложить кучей грубых и нагрузочных тестов в продакшне. Типа "ну а мне-то чо, что доказано? Главное чтобы работало стабильно"


Это довольно серьезный вопрос. Дело в том, что описание и доказательство работоспособности алгоритма обычно дается в независимом от языка реализации виде и поэтому - в предположении sequential consistent модели памяти. Думаю, SQ - это не то, что Вы хотели бы видеть у себя в программе. Работ, посвященных анализу конкурентных алгоритмов именно в модели памяти C++, немного (справедливости ради надо сказать, что их появляется все больше), и в основном они касаются простейших алгоритмов с двумя - тремя атомарными переменными. В случае алгоритмов с бОльшим числом взаимодействующих атомарных переменных анализ весьма затруднен. Инструментов для анализа довольно мало (я имею в виду открытых, open source) - кроме Thread Sanitizer, пожалуй, ничего и нет. Выхлоп, который дает TSan, довольно часто ставит меня в тупик...

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

Вообще, я скажу крамольную вещь, - модель памяти C++ так, как она описана в стандарте, нежизнеспособна. Это набор аксиом, весьма слабо коррелирующих с реальным положением дел в hardware. Это мое сугубое ИМХО, но оно косвенно подтверждается, например, нежеланием разработчиков Linux переходить на модель памяти C++11 (как Вы помните, модель памяти C++11 также распространяется на C11), и это нежелание они (Linux developers) весьма неплохо аргументируют.

NekZИли его подход к проектированию кода -- прямо на стэндапе показывал как подпирает свой код костылями (ещё и в виде макросов)
Видимо, на одном из выступлений я забыл произнести сакральную фразу про то, что "lock-free алгоритмы настолько многословны, что не вмещаются на страницу презентации, поэтому здесь я нагадил применил макросы". Я тоже не любитель макромагии, подтверждением чему может быть исходный код libcds в первозданном, так сказать, виде.
Ну и насчет костылей. Вы не поверите, пока не прочтете первоисточники, - половина lock-free кода - это именно костыли. Костыли для того, чтобы любое промежуточное состояние контейнера в процессе вставки/удаления элемента было персистентным. Поэтому я предпочитаю термин "трюки" ;-) Костыль - это кеши процессора.
...
Рейтинг: 0 / 0
Какую библиотеку посоветуете с потокобезопасными контейнерами?
    #39420952
Вася Уткин
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
khizmaxВообще, я скажу крамольную вещь, - модель памяти C++ так, как она описана в стандарте, нежизнеспособна. Это набор аксиом, весьма слабо коррелирующих с реальным положением дел в hardware. Это мое сугубое ИМХО, но оно косвенно подтверждается, например, нежеланием разработчиков Linux переходить на модель памяти C++11 (как Вы помните, модель памяти C++11 также распространяется на C11), и это нежелание они (Linux developers) весьма неплохо аргументируют.
А есть ссылка на эти аргументы? И есть ли где-то кросс-процессорная модель памяти, которая лучше?
Помимо memory_order_cunsume - кандидата на depricated, и не использования всех возможностей LL/SC - явных косяков не вижу.
...
Рейтинг: 0 / 0
Какую библиотеку посоветуете с потокобезопасными контейнерами?
    #39421001
khizmax
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Да, ссылки есть, например, одно из последних: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0124r1.html
Вообще, у Paul McKenney много об этом.
Но разговор идет не о том, что лучше/хуже, а о том, что они (модели памяти) различны. Ядро Линукса использует более "старую" модель (read/write barriers), которая возникла как раз из железа и зачастую более понятна в применении.
...
Рейтинг: 0 / 0
Какую библиотеку посоветуете с потокобезопасными контейнерами?
    #39421081
AlekseySQL
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Dima TСредствами ОС внутри потока понижай приоритет, по завершению возвращай как было. Не надо никаких менеджеров самодельных городить.
Для виндовса GetCurrentThread() и SetThreadPriority()

Спасибо, обдумаю ваше предложение.
...
Рейтинг: 0 / 0
Какую библиотеку посоветуете с потокобезопасными контейнерами?
    #39421125
Фотография CEMb
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Anatoly MoskovskyВы думаете за это не платят? Думаете, миллионы строк кода в ядре линукса написаны людьми которые не получают зарплату, просто как хобби? я не знаю. Но если тут проскочило слово "зарплата", значит кто-то кому-то платит зарплату с доходов этого opensourse/freeware, вопрос в том, как этот кто-то этот доход получает. Я, конечно, новичок во всех этих коммерческих операциях, но мне кажется, что free vs pay отличается только тем, что в начале, "деньги" или "стулья", если сначала стулья (раздаём ядро бесплатно, делает сопровождение/консультации/доработки/да просто берём трубку телефона - за деньги), то есть вполне ощутимый шанс остаться без денег, особенно если ты никому не известный разработчик, даже если супер-гениальный. Если я не прав, то мне бы сильно хотелось узнать, как можно заработать на freeware одинокому девелоперу, я этой темой давно интересуюсь.
khizmaxВообще, я скажу крамольную вещь, - модель памяти C++ так, как она описана в стандарте, нежизнеспособнаа можно небольшой экскурс по теме, как оно устроено, и почему оно плохо?
...
Рейтинг: 0 / 0
Какую библиотеку посоветуете с потокобезопасными контейнерами?
    #39421154
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
CEMbмне бы сильно хотелось узнать, как можно заработать на freeware одинокому девелоперу, я этой темой давно интересуюсь.
Там заработки на конкретных внедрениях и консалтинге. Потом это зарабатывание имиджа как разработчика, т.е. резюме конкретными делами. Для заработка на том и другом необходимо время.
...
Рейтинг: 0 / 0
Какую библиотеку посоветуете с потокобезопасными контейнерами?
    #39421224
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
khizmaxПривет,
я тот самый дядька, который гонит пургу на стендапах :-)

Это хорошо, что ты к нам пришёл, я очень рад.

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

Остальное пока не смотрел, встал на моделях многопоточной/задачной обработки, -- тоже интересно!
...
Рейтинг: 0 / 0
Какую библиотеку посоветуете с потокобезопасными контейнерами?
    #39421235
AlekseySQL
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Dima TСредствами ОС внутри потока понижай приоритет, по завершению возвращай как было. Не надо никаких менеджеров самодельных городить.
Для виндовса GetCurrentThread() и SetThreadPriority()

Я сижу под Linux и тут инет говорит, что приоритет меняется специальной структурой у объекта pthread_t. Такого объекта у меня нет, если все делать средствами qt.

Как находясь в методе run изменить приоритет в Linux?
...
Рейтинг: 0 / 0
Какую библиотеку посоветуете с потокобезопасными контейнерами?
    #39421247
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Не силен в линуксах. Гугл в помощь .
Немного почитал, как понимаю там еще права замешаны, снизить вроде сможешь, а обратно повысить только с правами суперпользователя (root, sudo), т.е. если твоя прога будет без прав, то никаким способом не повысит обратно. Только поток завершать.
...
Рейтинг: 0 / 0
Какую библиотеку посоветуете с потокобезопасными контейнерами?
    #39421305
Фотография CEMb
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dima TТам заработки на конкретных внедрениях и консалтинге. Потом это зарабатывание имиджа как разработчика, т.е. резюме конкретными делами. Для заработка на том и другом необходимо время.покажите мне хоть одного такого разработчика. Шароварщиков я много видел, работающих по одному. Но вот ни одного фриварщика с деньгами не видел. Там должен быть адовый порог входа, чтобы себе такой имидж в одиночку сделать и не быть задавленным более крупными командами, тем более если это опенсорс.
...
Рейтинг: 0 / 0
Какую библиотеку посоветуете с потокобезопасными контейнерами?
    #39421344
khizmax
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
CEMbа можно небольшой экскурс по теме, как оно устроено, и почему оно плохо?

уфф, вкратце так и не опишешь... Это тема для хорошего застолья с пивом на весь вечер. Ниже - мое ИМХО.
Я впервые услышал и увлекся lock-free структурами данных в 2006 году, то есть почти одновременно с началом дискуссии об atomic в C++11. Тогда (где-то 2008-2010 года) было несколько подходов к atomic и несколько жарких дискуссий в политкорректной форме, все документы есть на wg21 . Победил Hans Boehm и его подход.
Так как в то время C++11 ещё не было, приходилось писать свои atomic-велосипеды и, соотвественно, изучать модели памяти различных архитектур (честно скажу - от тех времен в голове мало что осталось). Причем весьма полезной была инсайдерская инфа от разработчиков того или иного процессора с различных форумов.

В стандарте модель памяти C++11 описана в терминах ячеек памяти, и memory order применяется тоже к ячейкам памяти. То есть если есть два различных адреса A и B, то, по стандарту, memory ordering, примененный к A и к B, никак не связаны. Отсюда вытекают некоторые подозрительные вещи: например, чтобы удовлетворить стандарту, предлагается вводить ненужные атомарные переменные с довольно тяжелыми операциями atomic fetch_add и memory_order_acq_rel ( вот разбор схемы Hazard Pointer в терминах C++11 memory model). Но реально memory order - это барьеры, на всех современных архитектурах они не применяются с конкретным адресам памяти, - они глобальны. На ассемблере барьер - это отдельная инструкция .
Часто возражают - а вот Intel Itanium, у него load/store с явным указанием acq/rel-семантики в одной инструкции, то есть тут барьер явно привязан к конкретному адресу, что и постулирует стандарт. Но если почитать спеку Intel Itanium по его модели памяти, то там часто путаница - в одном месте cказано, что memory ordering применяется к адресу, в другом - про адреса вообще ни слова. И самое главное - по инфе от разработчиков Итаниума, внутри все эти acq/rel-полубарьеры для load/store - это обычный mfence, то есть полный барьер, не связанный с адресом!
А теперь немного конспирологии ;-) Родителем memory model C++11 является, насколько я понимаю, Hans Boehm, - умный мужик ученый (любимое число - 42 ;), который на момент разработки стандарта работал... в лабораториях HP ! А кто такая HP? Это главный пропагандист архитектуры Itanium. А у Itanium load/store с явным указанием семантики acq/rel, - то, что мы сегодня видим в atomic load/store C++11.

Что ещё мне не нравится в стандарте - то, что memory order явно связан с потоками (threads). Да, несомненно, модель памяти предназначена именно для multithread. Но попытка каким-то образом связать load.acq одного потока с store.rel другого - это запутывание читателя! Один поток никак не может влиять на видимость значений в другом; часто пишут "поток A записал в M значение 42, но поток B не увидит 42 в M, пока/если..." и т.д. Все это чушь полная! Вернее, это производное рассуждение от истинной проблемы. Видимостью мы управлять вообще не можем. У современных процессоров кеши когерентные, так что "A записал, а B не увидел" - с точки зрения кеша такого быть не может. Но вот порядок/order , в котором B увидит то, что записал A, может быть другим. И виноват в этом не кеш, а небольшой костыль в виде store buffer между каждым ядром процессора и L1 кешем. Порядком мы управлять можем - это называется memory fence/barrier. И это отдельная инструкция, а не довесок/флаг в виде memory order к atomic load/store.

У меня большое подозрение, что C++11 memory model писалась исключительно для реализации spin lock. Но в конкурентных контейнерах применяются такие изощренные схемы, которым существующий memory ordering мал. Например, частый трюк при построении алгоритма конкурентного self-balanced дерева: операция поиска find() - неблокируемая, операции insert/erase - применяется fine grained locks на уровне узлов. То есть это схема single producer (только один поток может делать вращения) - multiple consumer (много потоков могут ходить по дереву, в том числе и по тем ветвям, которые в данный момент вращаются). При вращениях, особенно двойных, очень важен порядок, в котором указатели на узлы дерева (они, конечно же, atomic) модифицируются, иначе find()-потоки залезут не туда. Вопрос: какой тут должен быть memory ordering для чтения и записи node ptr?.. По сути, здесь достаточно store/store барьера во вращениях между каждым изменением указателя на узлы, то есть только в producer'е, чтобы задать порядок, в котором consumer'ы должны увидеть модифицируемые узлы поддерева. Как выразить это в C++11 memory model?..
...
Рейтинг: 0 / 0
Какую библиотеку посоветуете с потокобезопасными контейнерами?
    #39421402
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
CEMbDima TТам заработки на конкретных внедрениях и консалтинге. Потом это зарабатывание имиджа как разработчика, т.е. резюме конкретными делами. Для заработка на том и другом необходимо время.покажите мне хоть одного такого разработчика.
Nginx . Думаю у разработчика оплачиваемой работы хватает. Но таких единицы, кто в одиночку что-то массовое создал.
...
Рейтинг: 0 / 0
Какую библиотеку посоветуете с потокобезопасными контейнерами?
    #39421445
Фотография NekZ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Сорри, мужик, не хотел чтобы что-то грубо прозвучало про твои выступления, просто прими ожидаемую реакцию/критику публики со стендапов.
khizmaxУ современных процессоров кеши когерентные, так что "A записал, а B не увидел" - с точки зрения кеша такого быть не может. Но вот порядок/order , в котором B увидит то, что записал A, может быть другим. И виноват в этом не кеш, а небольшой костыль в виде store buffer между каждым ядром процессора и L1 кешем.

А разве не было заявлено много раз про то, что разные потоки, могут выполняться на разных процессорах , что будет триггерить перебрасывание кэшей между процессорами, что является серьёзным оверкиллом?
...
Рейтинг: 0 / 0
Какую библиотеку посоветуете с потокобезопасными контейнерами?
    #39421454
khizmax
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
NekZ,

Несомненно, было заявлено, но при этом когерентность кешей разных процессоров никто не отменяет. Именно поэтому в многопроцессорных системах так тормозит обращение к данным "чужого" процессора.
...
Рейтинг: 0 / 0
Какую библиотеку посоветуете с потокобезопасными контейнерами?
    #39421495
kealon(Ruslan)
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
khizmaxNekZ,

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

как-то довольно печальненько однако

простой интерлок переменной у меня на i7 упирается в 40 млн операц./c, с 150 млн./с на 1-м
...
Рейтинг: 0 / 0
Какую библиотеку посоветуете с потокобезопасными контейнерами?
    #39421677
Вася Уткин
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
khizmax , Но помимо привязки к процессору, модель памяти должна была быть привязана к компилятору, поэтому memory_order одновременно барьеры и для процессора и для компилятора.

Здесь есть как минимум 3 преимущества привязки барьеров к операциям:
1. Не все барьеры подходят для всех операций, для store (не подходят consume, acquire, acq_rel), а для load (не подходят release, acq_rel), и компилятор выдаёт compile-time ошибку. Этого он не может сделать для барьеров оторванных от операций.
2. Для компилятора, помимо изменения порядка - это ещё и управление spilling/filling всеми, в том числе неатомарными переменными.
3. Если процессоры делятся weak и strong модели памяти, то компилятор изначально всегда weak - и это даёт ему огромные возможности для оптимизаций. Барьеры не привязанные к операциям закрывают для переупорядочивания целые направления для всех операций, а не только для некоторых.

Насчет оптимизаций компилятора, допустим, у меня есть код (здесь Store-Load последовательность, которая без seq_cst могла бы переупорядочиваться):
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
#include <atomic>

// Atomic load-store
void test() {
    std::atomic<int> a, b, c;
    a.store(2, std::memory_order_seq_cst);          // movl 2,[a]; mfence;
    c.store(4, std::memory_order_relaxed);          // movl 4,[c];
    int tmp = b.load(std::memory_order_seq_cst);    // movl ,[tmp];
}


Я хочу дать возможность компилятору двигать c.store() в любую сторону: до a.store() или после b.load() - это даст компилятору больше манёвров для оптимизации. И в данном случае компилятор это сделать может.

Теперь перепишу этот код, как если бы мы делали с барьерами памяти отделенными от операций (для корректности оставлю переменные атомарными но всегда в них буду использовать самую слабую relaxed):

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
#include <atomic>

// Atomic load-store
void test() {
    std::atomic<int> a, b, c;
    a.store(2, std::memory_order_relaxed);                 // movl 2,[a]; 
    std::atomic_thread_fence(std::memory_order_seq_cst);   // mfence - (1) here?
    c.store(4, std::memory_order_relaxed);                 // movl 4,[c];
    //std::atomic_thread_fence(std::memory_order_seq_cst);   // mfence - (2) or here?
    int tmp = b.load(std::memory_order_relaxed);           // movl [b],[tmp];
}



В какой бы из 2-ух позиций я не вставил atomic_thread_fence( memory_order_seq_cst ) - это всегда закрывает как минимум одно направление для оптимизации. Компилятор не может понять к какой операции относится atomic_thread_fence-барьер, и какую операцию можно перемещать свободно, а какую нет.

khizmaxВ стандарте модель памяти C++11 описана в терминах ячеек памяти, и memory order применяется тоже к ячейкам памяти. То есть [b]если есть два различных адреса A и B, то, по стандарту, memory ordering, примененный к A и к B, никак не связаны
. Отсюда вытекают некоторые подозрительные вещи: например, чтобы удовлетворить стандарту, предлагается вводить ненужные атомарные переменные с довольно тяжелыми операциями atomic fetch_add и memory_order_acq_rel

А что имеется ввиду под выделенным?

Например, если мы применим seq_cst к store(A) и последующем load(B), то гарантировано будет предотвращено Store-Load-переупорядочивание только для этих двух операций, и ни для каких больше.

Следующий код (между c.store() и b.load() может не генерироваться mfence, про исключения вы наверное знаете):
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
#include <atomic>

// Atomic load-store
void test() {
    std::atomic<int> a, b, c;
    a.store(2, std::memory_order_seq_cst);          // movl 2,[a]; mfence;
    c.store(4, std::memory_order_release);          // movl 4,[c];
    int tmp = b.load(std::memory_order_seq_cst);    // movl [b],[tmp];
}



На всех типичных компиляторах x86_64 может быть пере-упорядочен так:

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
#include <atomic>

// Atomic load-store
void test() {
    std::atomic<int> a, b, c;
    a.store(2, std::memory_order_seq_cst);          // movl 2,[a]; mfence;
    int tmp = b.load(std::memory_order_seq_cst);    // movl [b],[tmp];
    c.store(4, std::memory_order_release);          // movl 4,[c];
}



c.store(rel); b.load(seq); могут быть переупорядочены в b.load(seq); c.store(rel);

Мало того, на других компиляторах или процессорах могут быть и другие изменения порядка:
a.storeA(seq_cst); c.load(acq_rel); может быть переупорядочен в c.load(acq_rel); a.store(seq_cst);
...
Рейтинг: 0 / 0
Какую библиотеку посоветуете с потокобезопасными контейнерами?
    #39421781
khizmax
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Вася Уткин, я ждал этого вопроса, про оптимизации компилятора ;-) Вы уже все сами ответили - да, барьеры также являются и барьерами компилятора. Полагаю, C++11 memory model для компиляторов был головной болью, ибо запрещал практически все оптимизации (речь, конечно, об atomic), - все они рассчитаны на один поток. Например, GCC, объявив GCC-4.8 "C++11 ready", только к GCC-6 восстановил большую часть оптимизаций (это мое наблюдение и найденные обмолвки/слухи/тесты в инете, пруфа не дам).
Но почему они (барьеры) должны быть обязательно прикреплены к atomic load/store/RMW?..
load(acquire) - это

load x
membar LoadLoad | LoadStore

store( release ) - это

membar LoadStore | StoreStore
store x

Вот вам явные (полу)барьеры с relaxed load/store. Они же - барьеры компилятора (они же - ассемблер Sparc; пожалуй, у Sparc была наиболее прямая memory model, без излишеств, но которая позволяла всё).
Это та модель, которая применялась до C++11, которая применяется сейчас в ядре Linux и которая прямо вытекает из железа.
И здесь барьеры не привязаны к ячейкам памяти, которые читаются/пишутся. Это просто явное указание упорядочения load/store.
Именно это я и "имел в виду под выделенным" - барьер не привязан явно к адресу. Если вы внимательно прочтете ту ссылку, которую я давал, не весь документ, а часть про Hazard Pointer, - увидите: там ради удовлетворения стандарта (которого на момент написания ещё не было, но он активно обсуждался) вводится ненужная для HP атомарная переменная, через которую синхронизируются потоки с помощью RMW. И все потому, что в HP atomic.load(A, acquire) и тут же atomic.store(B, release) - два разных адреса, а два разных адреса по C++11 не синхронизируются.

В общем, чем больше я работаю с atomic/memory ordering, - тем больше у меня вопросов. Maybe, это потому, что в свое время я начитался запрещенной литературы мануалов по различным архитектурам (кстати, могу сказать, - по большей части многотомное и бесполезное чтиво, только запутывает, начинаешь с подозрением относится даже к регистровым операциям).
Мне все больше кажется, что C++11 memory model - это лишь первая итерация, ещё далекая до идеала. И я рад, что нашлись линуксоиды-ядерщики, которые задают комитету похожие вопросы, - значит, дискуссия продолжится и решение будет найдено.
...
Рейтинг: 0 / 0
Какую библиотеку посоветуете с потокобезопасными контейнерами?
    #39421846
Вася Уткин
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
khizmaxПолагаю, C++11 memory model для компиляторов был головной болью, ибо запрещал практически все оптимизации (речь, конечно, об atomic) , - все они рассчитаны на один поток. Например, GCC, объявив GCC-4.8 "C++11 ready", только к GCC-6 восстановил большую часть оптимизаций (это мое наблюдение и найденные обмолвки/слухи/тесты в инете, пруфа не дам).
Строго говоря, C++11 memory model не запрещает все оптимизации, мало того она запрещает оптимизаций значительно меньше, чем запрещают атомарные операции применяемые в ядре Linux. А то, что конкретно старые версии GCC 4.8 - 6.0 не умели оптимизировать C++11 memory model - это проблема недоделанного компилятора. А в clang или icc с этим все заметно лучше.

khizmax вводится ненужная для HP атомарная переменная, через которую синхронизируются потоки с помощью RMW. И все потому, что в HP atomic.load(A, acquire) и тут же atomic.store(B, release) - два разных адреса, а два разных адреса по C++11 не синхронизируются.
Не понял про какое именно место в Hazard Pointer вы говорите. Но если покажите конкретную строчку(и) кода в PDF или у вас в libcds - смогу что-либо конкретное ответить.


Вот в таком коде стандарт C++11 может переместить c.store() как до a.store(), так и после b.load().
Мало того, даже скомпилированный код может быть переупорядочен процессором подобным образом:
c.store(relaxed) <-> b.load(seq_cst) на x86_64: https://godbolt.org/g/Tft2vw
a.store(seq_cst) <-> c.store(relaxed) на PowerPC: https://godbolt.org/g/oZGB4x

Вы, например, как бы переписали данный код с барьерами не привязанными к операциям?

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
#include <atomic>

// Atomic load-store
void test() {
    std::atomic<int> a, b, c;
    a.store(2, std::memory_order_seq_cst);          // movl 2,[a]; mfence;
    c.store(4, std::memory_order_relaxed);          // movl 4,[c];
    int tmp = b.load(std::memory_order_seq_cst);    // movl [b],[tmp];
}
...
Рейтинг: 0 / 0
Какую библиотеку посоветуете с потокобезопасными контейнерами?
    #39421900
Вася Уткин
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Поправил:
Вася Уткин a.store(seq_cst) <-> c.load(relaxed) c.store(relaxed) на PowerPC: https://godbolt.org/g/oZGB4x
...
Рейтинг: 0 / 0
Какую библиотеку посоветуете с потокобезопасными контейнерами?
    #39422115
AlekseySQL
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
NekZAlekseySQL,

Смотрели в boost::lockfree?

Посмотрел, и разочаровался: у очереди один метод push, который Not Thread-safe ( http://www.boost.org/doc/libs/1_63_0/doc/html/boost/lockfree/queue.html). У меня все наоборот: много писателей (дочерние потоки) и один читатель (основной поток).
...
Рейтинг: 0 / 0
Какую библиотеку посоветуете с потокобезопасными контейнерами?
    #39422117
Фотография Anatoly Moskovsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
AlekseySQLПосмотрел, и разочаровался: у очереди один метод push, который Not Thread-safe ( http://www.boost.org/doc/libs/1_63_0/doc/html/boost/lockfree/queue.html). У меня все наоборот: много писателей (дочерние потоки) и один читатель (основной поток).
Странно, а по ссылке, что вы привели, написано, что он Thread-safe
Вообще было бы странно если бы операции модификации очереди, которая по дизайну потокобезопасна, вдруг оказались недопустимы в потоках )))
...
Рейтинг: 0 / 0
Какую библиотеку посоветуете с потокобезопасными контейнерами?
    #39422121
Фотография Anatoly Moskovsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Вася УткинНасчет оптимизаций компилятора, допустим, у меня есть код (здесь Store-Load последовательность, которая без seq_cst могла бы переупорядочиваться):
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
#include <atomic>

// Atomic load-store
void test() {
    std::atomic<int> a, b, c;
    a.store(2, std::memory_order_seq_cst);          // movl 2,[a]; mfence;
    c.store(4, std::memory_order_relaxed);          // movl 4,[c];
    int tmp = b.load(std::memory_order_seq_cst);    // movl [b],[tmp];
}



Я хочу дать возможность компилятору двигать c.store() в любую сторону: до a.store() или после b.load() - это даст компилятору больше манёвров для оптимизации. И в данном случае компилятор это сделать может.

Странно, я всегда думал что через load/store совмещенный с seq_cst компилятору нельзя двигать операции в обе стороны (так же как и через release/acquire в одну сторону), иначе например мьютекс не будет работать.
Т.е. мое понимание было что load/store эквивалентно неатомарным операциям + отдельный барьер.
И весь спор про разницу моделей С++ и линукса ни о чем кроме синтаксиса.
Нет?
...
Рейтинг: 0 / 0
Какую библиотеку посоветуете с потокобезопасными контейнерами?
    #39422157
Вася Уткин
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Anatoly MoskovskyВася УткинНасчет оптимизаций компилятора, допустим, у меня есть код (здесь Store-Load последовательность, которая без seq_cst могла бы переупорядочиваться):
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
#include <atomic>

// Atomic load-store
void test() {
    std::atomic<int> a, b, c;
    a.store(2, std::memory_order_seq_cst);          // movl 2,[a]; mfence;
    c.store(4, std::memory_order_relaxed);          // movl 4,[c];
    int tmp = b.load(std::memory_order_seq_cst);    // movl ,[tmp];
}



Я хочу дать возможность компилятору двигать c.store() в любую сторону: до a.store() или после b.load() - это даст компилятору больше манёвров для оптимизации. И в данном случае компилятор это сделать может.

Странно, я всегда думал что [b]через load/store совмещенный с seq_cst компилятору нельзя двигать операции в обе стороны
(так же как и через release/acquire в одну сторону), иначе например мьютекс не будет работать.
Т.е. мое понимание было что load/store эквивалентно неатомарным операциям + отдельный барьер.
И весь спор про разницу моделей С++ и линукса ни о чем кроме синтаксиса.
Нет?
Выделенное не верно, в стандарте написано по другому, но запутанно, и вы его читали, а раз не поняли - поэтому зайду с другой стороны.
Я покажу во что компилятор компилирует load/store совмещенный с seq_cst, и покажу какие переупорядочивания он оставляет процессору.
А раз компилятор оставляет возможность таких переупорядочиваний процессору, значит и сам компилятор может делать эти же переупорядочивания .

Я покажу, как в этом коде процессор может переместить c.sotre(relaxed) как до a.store(seq_cst), так и после b.load(seq_cst):


1. Посмотрим что возможно на уровне asm-инструкций : https://en.wikipedia.org/wiki/Memory_ordering#In_symmetric_multiprocessing_.28SMP.29_microprocessor_systems
* x86_64 - strong memory model - allows Store-Load reordering (if there is no MFENCE) - правильно?
* PowerPC - weak memory model - allows Store-Store reordering (if there is no SYNC) - правильно?

2. Теперь посмотрим во что GCC компилирует "load/store совмещенный с seq_cst":
* x86_64 - может переупорядочить Store-Load т.к. между ними нет MFENCE:


* PowerPC - может переупорядочить Store-Store т.к. между ними нет sync:


В итоге получается, что один и тот же код скомпилированный под разные платформы может иметь одно из двух переупорядочиваний:
c.store(relaxed) <-> b.load(seq_cst) на x86_64: https://godbolt.org/g/Tft2vw
a.store(seq_cst) <-> c.store(relaxed) на PowerPC: https://godbolt.org/g/BTQBr8


Мало того, теоретически, но обычно не используют в компиляторах, семантика seq_cst может иметь 4 реализации на x86_64:

1. LOAD (without fence) and STORE + MFENCE
2. LOAD (without fence) and LOCK XCHG
3. MFENCE + LOAD and STORE (without fence)
4. LOCK XADD ( 0 ) and STORE (without fence)

Где 1 - это в GCC, 2 - это Clang & MSVC - по сути одно и тоже, очищает Store-Buffer после STORE
А 3 и 4 - не используют в компиляторах - очищают Store-Buffer перед LOAD

Так вот если бы некий компилятор использовал 3 и 4 реализацию seq_cst на x86_64, то была бы возможность переупорядочивания:
a.store(seq_cst) <--> c.load(relaxed)

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
#include <atomic>

// Atomic load-store
void test() {
#include <atomic>

// Atomic load-store
void test() {
    std::atomic<int> a, b, c;
    a.store(2, std::memory_order_seq_cst);          // movl 2,[a]; 
    int tmp1 = c.load(std::memory_order_relaxed);          // movl [c],[tmp1];
    int tmp = b.load(std::memory_order_seq_cst);    // mfence; movl [b],[tmp];
}
...
Рейтинг: 0 / 0
25 сообщений из 82, страница 2 из 4
Форумы / C++ [игнор отключен] [закрыт для гостей] / Какую библиотеку посоветуете с потокобезопасными контейнерами?
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]