Как я могу загрузить значения из памяти, не загрязняя кеш?

Я хочу прочитать ячейку памяти, не загрязняя кеш. Я работаю на машине X86 Linux. Я попытался использовать инструкцию ассемблера MOVNTDQA:

  asm("movntdqa %[source], %[dest] \n\t"
      : [dest] "=x" (my_var) : [source] "m" (my_mem[0]) : "memory");

my_mem — это int*, выделенный с помощью new, my_var — это int.

У меня есть две проблемы с этим подходом:

  1. Код компилируется, но при его запуске появляется ошибка «Недопустимая инструкция». Есть идеи, почему?
  2. Я не уверен, какой тип памяти выделяется с помощью new. Я бы предположил, что ВБ. Согласно документации, инструкция MOVNTDQA будет работать только с памятью типа USWC. Как узнать, с каким типом памяти я работаю?

Подводя итог, мой вопрос:

Как я могу прочитать ячейку памяти, не загрязняя кеш на машине X86? Мой подход в правильном направлении, и можно ли его исправить?

Спасибо.


person Anna    schedule 12.08.2009    source источник
comment
Этот вопрос связан? stackoverflow.com/ вопросы/851286/   -  person sharptooth    schedule 12.08.2009
comment
Я думаю, это связано :), но, к сожалению, этот вопрос/ответ не помогает мне с этим вопросом.   -  person Anna    schedule 12.08.2009
comment
О, еще одно: я не уверен, что это вообще возможно :-/ Я очень надеюсь, что это возможно.   -  person Anna    schedule 12.08.2009


Ответы (2)


Проблема с инструкцией movntdqa с %%xmm в качестве цели (загрузка из памяти) заключается в том, что этот insn доступен только с SSE4.1 и выше. Это означает, что более новый Core 2 (45 нм) или i7 пока только. Обратный путь (сохранение данных в памяти) доступен в более ранних версиях SSE.

Для этой инструкции процессор перемещает данные в один очень маленький из очень немногих буферов чтения (Intel не указывает точный размер, но предполагает, что он находится в диапазоне 16 байт), где они легко доступны, но выбрасываются. после нескольких других загрузок.

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

Помните, что после этого вам нужно использовать sfence insn.

Предварительная выборка существует в двух вариантах: prefetcht0 (предварительная выборка данных во всех кешах) и prefetchnt (предварительная выборка невременных данных). Обычно упреждающая выборка во всех кешах является правильной, для цикла потоковой передачи данных последнее было бы лучше, если вы последовательно используете инструкции потоковой передачи.

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

person Gunther Piez    schedule 15.08.2009

MOVNTDQA доступен только с SSE.

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

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

person moonshadow    schedule 12.08.2009
comment
У меня есть два ядра на одном процессе - одно из них сильно использует кеш, а другое имеет более низкий приоритет, и поэтому я пытаюсь уменьшить его использование кеша. На этой машине кэш L2 является общим для двух ядер, поэтому я хотел бы, чтобы память загружалась напрямую в L1 или в регистры (в программе с более низким приоритетом). Не могли бы вы уточнить, как использование инструкций предварительной выборки и аннулирования может помочь мне в этом случае? Большое спасибо. - person Anna; 12.08.2009
comment
Моя мысль заключалась в том, чтобы сделать так, чтобы процесс с низким приоритетом явно выбрасывал свои строки кэша, как только он заканчивал с ними работать, что позволяло бы перезаполнять их раньше, чем могла бы в противном случае разрешить политика управления кэшем ЦП, и, возможно, организовывать высокий приоритет. приоритетный процесс для выдачи предварительной выборки в особо дорогих разделах. Однако не уверен, насколько такой подход поможет в вашем сценарии. - person moonshadow; 12.08.2009
comment
@moonshadow: процессоры не всегда хорошо решают, что кэшировать. Это явная причина, по которой существует инструкция movntdqa. Это для потоковой передачи данных, однажды использованных, больше никогда не трогали (по крайней мере, не слишком рано ;-)). Что касается вспомогательного потока, это может быть жизнеспособным, если есть другой доступный поток, который иначе нельзя использовать полностью - на ум приходит гиперпоточность. Но в большинстве случаев вы получите лучший результат с двумя потоками, выполняющими полную работу и использующими явные инструкции предварительной выборки. - person Gunther Piez; 15.08.2009