Привет, лор.
Недавно тут у нас состоялась небольшая дискуссия о том, как лучше организовывать доступ к данным из разных тредов Гонка данных - тонкие тонкости?
Дискуссия, в целом, в классическом лоровском стиле: с одной стороны хорошие, правильные программисты, поясняют за UB и атомики, с другой - поехавшие наркоманы, которые пытаются пользоваться особенностями CPU. Я был вынужден выступить в дискуссии (частично, только из соображений производительности) на стороне наркоманов. Просто потому что иногда нужно чтобы софт работал быстрее, даже несмотря на то что яйцами в пилораму.
От товарища Marvel поступило такое возражение:
Так запись в atomic_uint32_t с relaxed ordering в релизе на Intel сгенерирует код, идентичный обычному присвоению uint32_t (проверено)
В ассемблерном выводе видно, что это немного не так. Но насколько действительно пострадает (если пострадает) производительность от использования atomic с relaxed ordering вместо обычных переменных?
Вот наколеночный тест https://gist.github.com/vmxdev/31c377f55d6717fce86c3b1160c89017
Устроен он так: работают три потока - продюсер на атомиках, продюсер на обычных переменных и потребитель.
Продюсеры просто в цикле увеличивают на единицу элементы массива, потребитель спит, потом просыпается, печатает что там насчитали производители, и опять засыпает. Две строки вывода это значения элементов в разных массивах. Первая строка - «обычные» переменные, вторая - на атомиках. Чем больше число, тем больше успел наувеличивать поток.
На моих железках этот тест дает (с довольно сильным разбросом) устойчиво более быстрый код с «обычными» переменными на x64 (до 2-х раз, в зависимости от количества элементов в массиве, с одним элементом барьер на ассемблере не нужен). На ARM (у меня только 32-битный) - практически та же картина, атомики даже еще немного медленнее (до 3-х раз).
Интересно, можно ли как-то разогнать код с атомиками? Если кто-то знает и может подсказать, было бы отлично.
Возможно, у меня старые компиляторы, и в новых атомики быстрее. Если кто-то даст результаты со свежими gcc и clang (тест лучше запускать несколько раз, хвоста достаточно) - было бы тоже неплохо.