Comments
Спасибо за обзор. Подскажите, а есть ли готовый анализатор для встраиваемых систем? Иногда надо понять, успеет ли микроконтроллер прожевать прерывание, или стоит ограничиться только установкой флага и обрабатывать в основном цикле.
Имхо, запись в память все же не настолько бесплатна.
Да, проц может её делать в бекграунде, но для этого придется считать линию в кеш (предварительно вытеснив что-то из него), обновить её и записать обратно. Т.е. как минимум какие-то данные из кеша будут вытеснены почем зря. А на NUMA системе записываемая линия будет ещё и инвалидирована на всех нодах.
Понятное дело, что если данные надо сохранить, то писать в память придется, хочется того или нет. Но иногда бывают случаи, что надо установить флаг, например, — если это надо делать очень часто, то лучше проверить текущее состояние флага и записывать в память только тогда, когда старое значение отличается от нового.
Это из серии «Тормозите лучше в папу. Папа мягкий. Он простит.»

Да, теоретически можно придумать ситуацию, когда вы пишите флаг часто, реально меняете его редко, у вас при этом большая NUMA-система и всё такое прочее… но это всё жуткая экзотика.

На практике вы линию из кеша не занимаете, она вначале во write combining buffer попадает. Кстати именно из-за write combining зачастую предлагаемый вами алгоритм будет скорее пессимизацией. Почитайте на досуге.
придется считать линию в кеш (предварительно вытеснив что-то из него), обновить её и записать обратно. Т.е. как минимум какие-то данные из кеша будут вытеснены почем зря.

А разве нет инструкции для записи в память минуя кеш не вытесняя при этом из него другие данные? Насколько я помню для чтения есть инструкции (non-temporal) которые позволяют считать из памяти в регистры не кешируя (на случай если мы хотим один раз вычитать что-то не вытеснив при этом более важные оперативные данные из кеша). Есть ли что-то подобное для записи?

Есть и на чтение, и на запись. Но сценарий это довольно редкий, и чтобы его использовать, должны быть очень веские основания.

Касательно CAS: 10-15 тактов — это действительно оптимистичная ситуация, когда только одно ядро лезет в память. Когда несколько ядер теребят одну и ту же переменную, задержки значительно возрастают: помимо того, что ядра становятся в очередь, так и ещё и шина данных начинает ругаться в стиле «вас много, а я одна» и замедляет обслуживание.

Делал как-то тест: запускал потоки, которые в бесконечном цикле увеличивали переменную, а зачем через секунду смотрел её значение. Результаты для процессора Core i7-2600K 4 GHz, 4 cores / 4 threads (HT off): 1 ядро — 22 такта на инкремент, 2 ядра и выше — 61*N тактов на инкремент, где N — число потоков.
Примечание: если зафиксировать affinity до 1 ядра, то выходит 13 такта на инкремент.

Поэтому когда я смотрю на совеременные 32-поточные процессоры, становится немного по себе от факта, что накладные расходы на синхронизацию могут превысить выгоду от распараллеливания.
Поэтому когда я смотрю на совеременные 32-поточные процессоры, становится немного по себе от факта, что накладные расходы на синхронизацию могут превысить выгоду от распараллеливания.
Алгоритмы обработки нужно изначально под это затачивать. «Небольшую» параллелизацию лучше обеспечивают всякие SSE/AVX/AVX2/AVX512…
> Алгоритмы обработки нужно изначально под это затачивать. «Небольшую» параллелизацию лучше обеспечивают всякие SSE/AVX/AVX2/AVX512…

А что мешает использовать и параллелизацию, и векторизацию?
Просто указываю на то, что при большом количестве ядер гранулярность должна быть ниже, чтобы избежать больших расходов на CAS-операции.
поэтому на всяких Phi, даже в сильно-параллельных задачах и пр. приходится от нее отказываться, т.к atomic операции тормозят.

Насчёт правильных переходов — в Golang принято после каждого шага проверять if err != nil, и обычно, конечно, ошибки нет, потому условие не выполняется. Получается это плохо влияет на возможности по предсказанию? Или ЦП подстроится сам?

Про предсказание ветвлений есть отдельная статья.

Подстроится — но всё-таки это не совсем бесплатно. На очень простых функциях может быть заметно, но даже там — потери на фоне, собственно, стоимости вызова функции — копейки…
Интересно, как это:

Так же как и для любого типа кэша, существует стоимость промаха TLB; для x64 она колеблется между 7-21 тактами ЦП [7cpu].


согласуется с этим:

Однако, что сложнее найти, так это информацию о времени доступа к основной ОЗУ. [Levinthal] оценивает его в 60нс (~ 180 тактов, если процессор работает на частоте 3ГГц).


ведь промах TLB ведёт к обращению к страничным таблицам, а обращений этих может быть до 5 на современных x64 (без виртуализации, с виртуализацией — до 25), и адрес каждого обращения получается из предыдущего, т.е. их нельзя распараллелить.
Типичная ёмкость TLB-кеша в современных CPU — это всего-навсего 128 записей. В идеальном случае при 4K страницах этого хватает на полмегабайта, а если данные расположены «неплотно», то и ещё на меньшие обьёмы (вплоть до «предельно паталогического» случая, когда 129 обращений к 129 байтам приводят к тому, что TLB-кеш постоянно перезагружается). А ёмкости L3 кеша — существенно больше. Так что ходить в ОЗУ при промахе не приходится.

Кроме того совершенно неясно с какого перепугу вы решили, что если информация о конкретной странице будет выгружена из TLB кеша, то и информация о каталогах и прочем тоже будет выгружена. Не будет.

То есть TLB-промах, как правило, — это примерно один запрос в L3 (а не в оперативную память)… ну и дополнотильные пляски с интерпретацией этой информации…

Конечно если вы весь TLB-кеш сбросите — там уже другие числа будут…
совершенно неясно с какого перепугу вы решили, что если информация о конкретной странице будет выгружена из TLB кеша, то и информация о каталогах и прочем тоже будет выгружена. Не будет.


А она вообще там есть? Т.е. помимо записей вида (например, для 32-битных 4К страниц) 0xvvvvvxxx -> 0xpppppxxx в TLB хранятся записи вида 0xvvxxxzzz -> 0xppxxxzzz для каталогов (и они отличны от записей для страниц с адресами 0xvvxxxzzz)?
А она вообще там есть?

Отвечу сам себе: есть, но не в TLB. Документация intel выделяет эту информацию в отдельные структуры, называемые paging structure caches.
Only those users with full accounts are able to leave comments. Log in, please.