All streams
Search
Write a publication
Pull to refresh
11
0
Андрей Зворыгин @don-dron

Backend developer

Send message

Именно, спасибо!

Да это правда, процессор реордерит операции, я это не хотел рассказывать раньше времени, но уже выше обновил

Отличное объяснение спасибо, не знал таких тонкостей, надо как-то в будущем будет упомянуть этот аспект

Попробую поискать информацию об этом, что то новое для меня, к сожалению на Intel не воспроизводится( надо найти AMD

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

Согласен, но, к сожалению, далеко не везде можно обойтись параллельным исполнением с синхронизацией только на join) В highload проектах, например GC, СУБД и других без этого никак не получится

Хорошее замечание) по факту, да, в нашей модели должен быть еще store барьер после завершения инструкций каждого потока, я постараюсь рассмотреть этот пример еще раз в следующей статье и подробнее рассмотреть load barrier, мне уже кажется , что я принял слишком не точное его определение, которое может запутать, если действительно хочется разобраться советую почитать https://www.felixcloutier.com/x86/lfence и https://en.wikipedia.org/wiki/MESI_protocol (раздел про Memory barriers)

Согласен с этой точкой зрения, я буквально полгода назад придерживался её же. Но к сожалению, современные ограничения и в частности барьеры дают такое сильное влияние, что оно рушит всю картину. Появление acquire/release и вообще моделей памяти - высокоуровневых абстракций , модели happens before , связано со слабыми моделями памяти процессора. Для меня это тот случай, когда детали реализации оказывают решающее влияние. Иногда встречаю людей, которые живут в мире некоторых правил и не сталкиваются с такими ужасами, но стараются сыграть в многопоточность и совершают примитивные ошибки. Если не заходить дальше простых элементов, это не конечно нужно, но если вам нужен первоманс на той же джаве, без этого не обойтись.

Как раз и не должен завершаться) это значит , что мы исключили вариант (0,0), вообще странная ситуация, по спецификации mfence это комбинация lfence и sfence

Можно конечно, но тема блокировок - отдельная, здесь гвоздем программы были барьеры. Локи/блокировки дают очень классный (иногда колоссальный) оверхед на процессор. Особенно видно на конкурентных структурах данных. Условно, если написать стэк на DCAS (или стек на двух CAS), а потом сравнить его с стэком под локом, то на бенчмарках можно увидеть неприятную картину - количество операций в секунду может быть и в 3+ раза меньше на стэке под локом (будет зависеть от количества потоков).

Конечно, в реальных бизнесовых проектах редко встретишь конкаренси ( и это хорошо ), но если и встречается, то ограничивается synchronized в Java и спинлоками/мьютексами/фьютексами в C/C++.

Тема про барьеры описанная здесь - одна из подводок к моделям памяти. В частности хочется рассказать про JMM в более простом ключе, а не так как это описано в её спецификации (без 100 грамм не разберешься).

Постарался не вводить лишние сущности в виде моделей памяти (SC интуитивно понятна - поэтому не считается)) По поводу инвалидации кэша тема вообще отдельная и непростая, строго говоря LFENCE работает сложнее и не просто "обновляет" кэш. https://www.felixcloutier.com/x86/lfence

Information

Rating
Does not participate
Location
Москва, Москва и Московская обл., Россия
Registered
Activity

Specialization

Backend Developer
Middle
Java
Java Spring Framework
Parallel programming
Low-level programming
High-loaded systems
Pure C
Unix
SQL