Что означают «невременные» обращения к памяти в x86

123

Это вопрос довольно низкого уровня. В сборке x86 есть две инструкции SSE:

MOVDQA xmmi, m128

и

MOVNTDQA xmmi, m128

В Руководстве разработчика программного обеспечения IA-32 говорится, что NT в MOVNTDQA означает Non-Temporal , и что в остальном это то же самое, что и MOVDQA.

У меня вопрос, что означает « Non-Temporal» ?

Натан Феллман
источник
6
Обратите внимание, что SSE4.1 MOVNTDQA xmmi, m128является загрузкой NT, тогда как все остальные инструкции NT являются сохранением, за исключением prefetchnta. В принятом здесь ответе, похоже, говорится только о магазинах. Это то, что я обнаружил в отношении NT-нагрузок . TL: DR: надеюсь, что CPU делает что-то полезное с подсказкой NT, чтобы минимизировать загрязнение кеша, но они не отменяют строго упорядоченную семантику «нормальной» WB-памяти, поэтому они должны использовать кеш.
Питер Кордес
5
Обновление: загрузка NT может не делать ничего полезного, кроме областей памяти UCSW на большинстве процессоров (например, семейство Intel SnB). Однако NT / streaming store определенно работают с обычной памятью.
Питер Кордес
4
@ Питер: Вы имеете в виду память USWC, верно? Я никогда раньше не слышал о памяти UCSW или USWC. Погуглить неправильную аббревиатуру не помогло :-)
Эндрю Бейнбридж
4
@AndrewBainbridge: Да, атрибут типа памяти WC. Некэшируемая спекулятивная запись-объединение. Думаю, я использовал UnCacheable с заглавной буквы и помнил, что он должен состоять из 4 букв. : P
Питер Кордес

Ответы:

147

Невременные инструкции SSE (MOVNTI, MOVNTQ и т. Д.) Не подчиняются обычным правилам когерентности кеша. Поэтому за невременными хранилищами должна следовать инструкция SFENCE, чтобы их результаты могли своевременно увидеть другие процессоры.

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

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

Источник: http://lwn.net/Articles/255364/

Эспоо
источник
15
Хороший ответ, я просто хотел бы указать, что на типе процессора с инструкциями NT, даже с невременными инструкциями (то есть нормальной инструкцией), кэш строк не «читается, а затем изменяется». Для обычной записи инструкции в строку, которой нет в кэше, строка резервируется в кэше, а маска указывает, какие части строки являются актуальными. На этой веб-странице это называется «без киосков в магазине»: ptlsim.org/Documentation/html/node30.html . Я не смог найти более точных ссылок, я слышал об этом только от парней, чья работа заключается в реализации симуляторов процессора.
Паскаль Куок
2
На самом деле ptlsim.org - это веб-сайт, посвященный симулятору процессора с точностью до цикла, точно так же, как и те ребята, которые рассказали мне о том, что «в магазине нет киосков». Я бы лучше упомянул и их, на случай, если они когда-нибудь увидят этот комментарий: unisim.org
Паскаль Куок
1
Из ответов и комментариев здесь stackoverflow.com/questions/44864033/… кажется, что это SFENCEможет не понадобиться. По крайней мере, в той же ветке. Не могли бы вы также посмотреть?
Serge Rogatch 02
1
@SergeRogatch, это зависит от того, о каком сценарии вы говорите, но да, есть сценарии, в которых sfenceэто требуется для хранилищ NT, тогда как это никогда не требуется только для обычных хранилищ. Хранилища NT не упорядочиваются по отношению к другим хранилищам (NT или нет) с точки зрения других потоков без расширения sfence. Однако для чтения из того же потока, что и хранилища, в этом нет необходимости sfence: данный поток всегда будет видеть свои собственные хранилища в программном порядке, независимо от того, являются ли они хранилищами NT или нет.
BeeOnRope 08
40

Эспо в значительной степени попадает в цель. Просто хотел добавить свои два цента:

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

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

Pramod
источник
вопрос о «вручную написанной сборке, использующей инструкции управления кешем». Я знаю, что вы явно сказали «закодировано вручную» насчет чего-то вроде JavaVM. Это лучший вариант использования? JavaVM / Compiler проанализировал статическое и динамическое поведение программы и использует эти невременные инструкции.
Пэт
4
Нельзя избегать использования известных свойств местности (или их отсутствия) вашей проблемной области, алгоритма или приложения. Избежать загрязнения кеша - действительно очень привлекательная и эффективная задача оптимизации. Кроме того, почему отвращение к сборке? Есть огромное количество возможностей для получения прибыли, которые компилятор не может использовать в своих
интересах
5
Определенно верно, что знающий программист низкого уровня может превзойти компилятор для небольших ядер. Это отлично подходит для публикации статей и сообщений в блогах, и я сделал и то, и другое. Они также являются хорошими дидактическими инструментами и помогают понять, что «на самом деле» происходит. По моему опыту, на практике, когда у вас есть реальная система, над которой работает много программистов, а правильность и ремонтопригодность важны, преимущества низкоуровневого кодирования почти всегда перевешиваются рисками.
Pramod
4
@Pramod тот же аргумент легко обобщается на оптимизацию в целом и на самом деле не входит в рамки обсуждения - очевидно, что компромисс уже был рассмотрен или иным образом признан неуместным, учитывая тот факт, что мы уже говорим о невременных инструкциях
awdz9nld
7

Согласно Руководству разработчика программного обеспечения для архитектур Intel® 64 и IA-32, том 1: Базовая архитектура, глава «Программирование с использованием расширений Intel Streaming SIMD (Intel SSE)»:

Кеширование временных и вневременных данных

Данные, на которые ссылается программа, могут быть временными (данные будут использоваться снова) или невременными (данные будут ссылаться один раз и не будут использоваться повторно в ближайшем будущем). Например, программный код обычно носит временный характер, тогда как мультимедийные данные, такие как список отображения в приложении трехмерной графики, часто не являются временными. Чтобы эффективно использовать кеши процессора, обычно желательно кэшировать временные данные, а не кэшировать невременные данные. Перегрузка кэшей процессора невременными данными иногда называется «загрязнением кешей». Команды управления кэшируемостью SSE и SSE2 позволяют программе записывать невременные данные в память таким образом, чтобы минимизировать загрязнение кешей.

Описание невременных инструкций по загрузке и хранению. Источник: Руководство разработчика программного обеспечения для архитектур Intel 64 и IA-32, том 2: Справочник по набору инструкций

ЗАГРУЗИТЬ (MOVNTDQA - загрузить подсказку с двойным четырехсловым без временного выравнивания)

Загружает двойное четверное слово из исходного операнда (второй операнд) в целевой операнд (первый операнд) с использованием невременной подсказки, если источником памяти является тип памяти WC (объединение записи) [...]

[...] процессор не считывает данные в иерархию кеша и не извлекает соответствующую строку кеша из памяти в иерархию кеша.

Обратите внимание, что, как комментирует Питер Кордес, это бесполезно для обычной памяти WB (с обратной записью) на текущих процессорах, потому что подсказка NT игнорируется (вероятно, потому, что нет предварительных выборок HW с поддержкой NT) и применяется полная строго упорядоченная семантика загрузки , prefetchntaможет использоваться как уменьшающая загрязнение нагрузка из памяти WB

СОХРАНИТЬ (MOVNTDQ - хранить упакованные целые числа с помощью вневременной подсказки)

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

[...] процессор не записывает данные в иерархию кеша и не извлекает соответствующую строку кэша из памяти в иерархию кеша.

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

Наконец, может быть интересно просмотреть заметки Джона Макалпина о вневременных хранилищах .

Chus
источник
3
SSE4.1 MOVNTDQAделает что-то особенное только в областях памяти WC (некэшируемая запись-объединение), например, в видеопамяти. Это совершенно бесполезно для нормальной памяти WB (с обратной записью) на текущем HW, подсказка NT игнорируется и применяется полная строго упорядоченная семантика загрузки. prefetchntaТем не менее, может быть полезен для уменьшения нагрузки на WB-память. Поддерживают ли текущие архитектуры x86 невременные нагрузки (из «нормальной» памяти)? ,
Питер Кордес
2
Это верно, NT-хранилища отлично работают с WB-памятью, они слабо упорядочены и обычно являются хорошим выбором для записи больших областей памяти. Но NT-нагрузки - нет. Бумажное руководство по x86 позволяет подсказке NT что-то делать при загрузке из памяти WB, но в текущих процессорах она ничего не делает . (Вероятно, потому что нет предварительных выборок HW, знающих NT.)
Питер Кордес
Я добавил соответствующую информацию к ответу. Большое спасибо.
chus
1
@LewisKelsey: NT- хранилища переопределяют тип памяти. Поэтому они могут быть слабо упорядочены по памяти WB. Главный эффект заключается в том, чтобы избежать RFO (очевидно, они отправляют недействительное сообщение, которое даже очищает другие грязные строки, когда они достигают mem). Они также могут стать видимыми вне очереди, поэтому им не нужно ждать, пока не будет зафиксировано предыдущее (обычное) хранилище с ошибками кэша или пока не будут получены данные при более ранней загрузке с ошибками кэша . то есть тип узкого места, о котором спрашивается в разделе Всегда ли память вне каждого ядра концептуально плоская / однородная / синхронная в многопроцессорной системе? ,
Питер Кордес
1
@LewisKelsey: Очистка машины для упорядочивания памяти может при необходимости уничтожить любые нагрузки из хранилища UC, чего не следовало делать раньше. Помимо этого, порядок фиксации не вступает в силу до тех пор, пока магазин не перестанет работать с вышедшей из строя серверной частью. Это не может произойти до тех пор, пока не будет выполнен uop адреса хранилища, после чего можно проверить тип памяти для адреса. Uop-адрес хранилища проверяет TLB при выполнении; именно так процессоры могут обнаруживать неисправные хранилища до их выхода из эксплуатации. Он не может дождаться, пока запись SB будет готова к фиксации в L1d; в этот момент исполнение уже прошло.
Питер Кордес