Как я могу загрузить значения из памяти, не загрязняя кеш?
Я хочу прочитать ячейку памяти, не загрязняя кеш. Я работаю над машиной X86 Linux. Я попытался использовать инструкцию ассемблера MOVNTDQA:
asm("movntdqa %[source], %[dest] \n\t"
: [dest] "=x" (my_var) : [source] "m" (my_mem[0]) : "memory");
my_mem - это int *, выделенный новым, my_var - это int.
У меня есть две проблемы с этим подходом:
- Код компилируется, но при запуске я получаю сообщение об ошибке "Недопустимая инструкция". Любые идеи, почему?
- Я не уверен, какой тип памяти выделяется новым. Я бы предположил, что ВБ. Согласно документации, инструкция MOVNTDQA будет работать только с типом памяти USWC. Как я могу узнать, на какой тип памяти я работаю?
Подводя итог, мой вопрос:
Как я могу прочитать ячейку памяти без загрязнения кэша на машине X86? Является ли мой подход в правильном направлении и может ли он быть исправлен для работы?
Спасибо.
Ответы
Ответ 1
Проблема с командой movntdqa с %% xmm как target (загрузка из памяти) заключается в том, что этот insn доступен только с SSE4.1 и включен. Это означает, что на данный момент более новый Core 2 (45 нм) или i7. Другой способ (сохранение данных в память) доступен в более ранних версиях SSE.
Для этой команды процессор перемещает данные в одно очень малое количество буферов чтения (Intel не указывает точный размер, но предполагает, что он находится в диапазоне 16 байт), где он легко доступен, но вызывается после нескольких других нагрузок.
И это не загрязняет другие кеши, поэтому, если у вас есть потоковые данные, ваш подход жизнеспособен.
Помните, что вам нужно использовать sfence insn впоследствии.
Предварительная выборка существует в двух вариантах: prefetcht0 (предварительная выборка данных во всех кэшах) и prefetchnt (предварительная выборка временных данных). Обычно предварительная выборка во всех кэшах является правильной вещью, поскольку для цикла потоковой передачи последнее будет лучше, если вы последовательно используете инструкции потоковой передачи.
Вы используете его с адресом объекта, который хотите использовать в ближайшем будущем, обычно несколько итераций вперед, если у вас есть цикл. Prefetch insn не ждет и не блокирует, это просто заставляет процессор начать получать данные в указанной ячейке памяти.
Ответ 2
MOVNTDQA доступен только с SSE.
Почему вы пытаетесь избежать использования кеша? Процессоры, как правило, неплохо решают, что выкинуть из кеша, когда. Если действительно нужно, одним из способов было бы организовать псевдоним области памяти, которую вы читаете, чтобы отображаться в вашем адресном пространстве с отключенным кэшированием и чтением оттуда.
Если то, что вы пытаетесь достичь, на самом деле сводит к минимуму влияние вашего кода на другой рабочий набор функций, хранящийся в кеше в то время, это должно выполняться путем выдачи соответствующих инструкций предварительной выборки и недействительности.