Как писать или читать память, не трогая кеш

c caching memory x86

3821 просмотра

2 ответа

Есть ли способ записи / чтения памяти без касания кэш-памяти L1 / L2 / L3 в процессорах x86?

И полностью ли аппаратно управляется кэш в процессорах x86?

РЕДАКТИРОВАТЬ: Я хочу сделать это, потому что я хочу сэмплировать скорость памяти и посмотреть, не ухудшается ли какая-либо часть производительности памяти.

Автор: Michael Tong Источник Размещён: 12.11.2019 09:14

Ответы (2)


16 плюса

Решение

Процессор действительно управляет своими собственными кешами аппаратного обеспечения, но x86 предоставляет вам несколько способов повлиять на это управление.

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

  1. Используйте невременные инструкции x86, они предназначены для того, чтобы сообщить процессору, что вы больше не будете повторно использовать эти данные, поэтому нет смысла сохранять их в кеше. Эти инструкции в x86 обычно называются movnt * (с суффиксом в соответствии с типом данных, например, movnti для загрузки обычных целых чисел в регистры общего назначения). Существуют также инструкции для потоковой загрузки / хранения, которые также используют аналогичную технику, но больше подходят для потоков с большим BW (при последовательной загрузке целых строк). Чтобы использовать их, либо кодируйте их во встроенной сборке, либо используйте встроенные функции, предоставляемые вашим компилятором, большинство из них называют это семейство _mm_stream_ *

  2. Измените тип памяти определенной области на uncacheable. Поскольку вы заявили, что не хотите отключать все кэширование (и это справедливо, поскольку это также включает код, стек, карту страницы и т. Д.), Вы можете определить конкретный регион, в котором находится набор данных вашего эталонного теста, как не кэшируемый, используя MTRR (регистры диапазона типов памяти). Есть несколько способов сделать это, вам нужно прочитать некоторую документацию для этого.

  3. Последний вариант заключается в обычном извлечении строки, что означает, что она изначально кэшируется, но затем вынуждает ее очистить все уровни кэша, используя специальную инструкцию clflush (или полный wbinvd, если вы хотите очистить весь кэш). Удостоверьтесь, что эти операции правильно ограничены, чтобы вы могли гарантировать, что они выполнены (и, конечно, не измеряйте их как часть задержки).

Сказав это, если вы хотите сделать все это только для того, чтобы время считывало вашу память, вы можете получить плохие результаты, поскольку большинство процессоров обрабатывают невременные или не кэшируемые обращения «неэффективно». Если вы выполняете принудительное чтение только из памяти, это лучше всего достигается путем манипулирования LRU кэшей путем последовательного доступа к набору данных, который достаточно велик, чтобы не помещаться ни в один кэш. Это приведет к тому, что большинство схем LRU (не все!) Сначала удаляют самые старые строки, поэтому в следующий раз, когда вы обернетесь вокруг, они должны появиться из памяти.

Обратите внимание, что для того, чтобы это работало, вам нужно убедиться, что ваш HW prefetcher не помогает (и случайно покрывает задержку, которую вы хотите измерить) - либо отключите его, либо сделайте доступ достаточно большим, чтобы он был неэффективным.

Автор: Leeor Размещён: 24.02.2015 11:49

7 плюса

Лиор прееты много перечислил наиболее « про » решения для вашей задачи. Я попытаюсь добавить к этому еще одно предложение, которое может достичь тех же результатов и может быть написано простым C с помощью простого кода. Идея состоит в создании ядра, аналогичного «Глобальному произвольному доступу», найденному в тесте HPCC Challenge .

Идея ядра заключается в том, чтобы случайным образом перепрыгивать через огромный массив значений 8B, который в два раза меньше размера вашей физической памяти (поэтому, если у вас 16 ГБ ОЗУ, вам нужен массив 8 ГБ, ведущий к элементам 1G из 8B). Для каждого прыжка вы можете прочитать, написать или RMW целевого местоположения.

Скорее всего, это измеряет задержку ОЗУ, поскольку случайный скачок через ОЗУ делает кеширование очень неэффективным . Вы получите крайне низкие показатели попадания в кэш, и если вы выполните достаточные операции с массивом, вы сможете измерить реальную производительность памяти. Этот метод также делает предварительную выборку очень неэффективной, так как нет обнаруживаемого шаблона.

Вы должны принять во внимание следующие вещи:

  1. Убедитесь, что компилятор не оптимизирует ваш цикл ядра (обязательно сделайте что-нибудь с этим массивом или сделайте что-нибудь со значениями, которые вы читаете из него).
  2. Используйте очень простой генератор случайных чисел и не храните целевые адреса в другом массиве (который будет кешироваться). Я использовал линейный конгруэнтный генератор . Таким образом, следующий адрес вычисляется очень быстро и не добавляет дополнительных задержек, кроме тех, которые установлены в ОЗУ.
Автор: VAndrei Размещён: 01.03.2015 08:56
Вопросы из категории :
32x32