Что такое подсказки локальности _mm_prefetch()?

руководство по использованию говорит только о void _mm_prefetch (char const* p, int i):

Получить строку данных из памяти, содержащую адрес p, в местоположение в иерархии кеша, заданное подсказкой местоположения i.

Не могли бы вы указать возможные значения для параметра int i и объяснить их значения?

Я нашел _MM_HINT_T0, _MM_HINT_T1, _MM_HINT_T2, _MM_HINT_NTA и _MM_HINT_ENTA, но я не знаю, является ли это исчерпывающим списком и что они означают.

Если для конкретного процессора я хотел бы знать, что они делают с Ryzen и новейшими процессорами Intel Core.

Ответ 1

Иногда внутреннее поведение лучше понимается в терминах команды, которую они представляют, а не как абстрактной семантики, данной в их описаниях.


Полный набор констант локальности, как сегодня,

#define _MM_HINT_T0 1
#define _MM_HINT_T1 2
#define _MM_HINT_T2 3
#define _MM_HINT_NTA 0
#define _MM_HINT_ENTA 4
#define _MM_HINT_ET0 5
#define _MM_HINT_ET1 6
#define _MM_HINT_ET2 7

как описано в этой статье о возможностях предварительной обработки сопроцессора Intel Xeon Phi.

Для процессоров IA32/AMD набор уменьшается до

#define _MM_HINT_T0 1
#define _MM_HINT_T1 2
#define _MM_HINT_T2 3
#define _MM_HINT_NTA 0
#define _MM_HINT_ET1 6

_mm_prefetch скомпилирован в разные инструкции на основе архитектуры и подсказки локальности

    Hint              IA32/AMD          iMC
_MM_HINT_T0           prefetcht0     vprefetch0
_MM_HINT_T1           prefetcht1     vprefetch1
_MM_HINT_T2           prefetcht2     vprefetch2
_MM_HINT_NTA          prefetchtnta   vprefetchnta
_MM_HINT_ENTA              -         vprefetchenta
_MM_HINT_ET0               -         vprefetchet0
_MM_HINT_ET1          prefetchtwt1   vprefetchet1
_MM_HINT_ET2               -         vprefetchet2

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

Когда строка предварительно загружена на уровень X, руководства (как Intel, так и AMD) говорят, что она также попала во все другие более высокие уровни (но для случая X = 3).
Я не уверен, что это действительно так, я считаю, что линия предварительно заполнена с соблюдением - к уровню кэша X и в зависимости от стратегий кэширования более высоких уровней (включительно vs не включительно), она может присутствовать или не присутствовать там тоже.

Другим атрибутом инструкций (v)prefetch является невременный атрибут.
Вневременные данные вряд ли будут повторно использованы в ближайшее время.
По моему мнению, данные NT хранятся в "потоковых буферах нагрузки" для архитектуры IA32 1 тогда как для архитектуры iMC она хранится в обычном кеше (используя в качестве способа идентификатор аппаратного потока), но с самой последней версией политики замены (так что это будет следующая высеченная строка, если это необходимо).
Для AMD руководство читает, что фактическое местоположение зависит от реализации, от программного невидимого буфера до выделенного невременного кеша.

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

Архитектуры IA32 и AMD не поддерживают и исключают невременную подсказку (пока), так как уровень невременного кэша определяется реализацией.
Архитектура iMC позволяет использовать ее с кодом местности _MM_HINT_ENTA.

1 Я понимаю, что это буферы WC. Питер Кордес разъяснил это в комментарии ниже: prefetchnta использует только буферы Line-Fill, если предварительно загружает регионы памяти USWC. В противном случае он предварительно вставляется в L1


Для справки здесь приведено описание инструкций

PREFETCHh

Выбирает строку данных из памяти, содержащую байт, указанный с помощью операнда источника, в местоположение в кэш-иерархию, указанную подсказкой локальности:

• T0 (временные данные) - данные выборки на всех уровнях иерархии кеша.
• T1 (временные данные относительно промахов кэша первого уровня) - данные выборки в кеш второго уровня и выше.
• T2 (временные данные в отношении промахов кэша второго уровня) - данные выборки в кеш уровня 3 и выше или выбор конкретной реализации.
• NTA (не временные данные по всем уровням кэша); - выборка данных в невременную структуру кеша и в место, близкое к процессору, минимизируя загрязнение кеша.

PREFETCHWT1

Выбирает строку данных из памяти, содержащую байт, указанный с помощью операнда источника, в местоположение в кэш-иерархию, указанную в намерении написать подсказку (чтобы данные вводились в "Исключительное состояние" посредством запроса на владение) и подсказка местности:

• T1 (временные данные по отношению к кешу первого уровня) - данные выборки в кеш второго уровня.

VPREFETCHh

                Cache  Temporal    Exclusive state
                 Level
VPREFETCH0       L1     NO          NO
VPREFETCHNTA     L1     YES         NO
VPREFETCH1       L2     NO          NO
VPREFETCH2       L2     YES         NO
VPREFETCHE0      L1     NO          YES
VPREFETCHENTA    L1     YES         YES
VPREFETCHE1      L2     NO          YES
VPREFETCHE2      L2     YES         YES