Разница между инструкциями PREFETCH и PREFETCHNTA

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

Так что же делает PREFETCHNTA, что отличается от инструкции PREFETCH?


person Abhishek Nikam    schedule 12.11.2018    source источник


Ответы (1)


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

На бумаге x86 ISA не указывает, как реализовать подсказку NT. http://felixcloutier.com/x86/PREFETCHh.html говорит: NTA ( невременные данные по отношению ко всем уровням кеша) — предварительная выборка данных в структуру невременного кеша и в местоположение, близкое к процессору, сводя к минимуму загрязнение кеша. То, как конкретная микроархитектура ЦП решит реализовать это, полностью зависит от архитекторы.


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

Что он делает на процессорах Intel, так это пропускает неинклюзивные внешние кеши. Так вот на Intel до Skylake-AVX512 он обходит L2 и заполняет L1d+L3. Но на SKX он также полностью пропускает кеш L3, потому что он меньше и не включает. См. раздел Поддерживают ли современные архитектуры x86 временные нагрузки. (из обычной памяти)?

На процессорах Intel с инклюзивным кэшем L3 (который он не может обойти) он уменьшает загрязнение L3, ограничиваясь предварительной выборкой в ​​один из способов ассоциативного инклюзивного кэша L3. (Это обычно что-то вроде ассоциативности с 16 путями, поэтому общая емкость, которая может быть загрязнена prefetchnta, составляет всего ~ 1/16 от общего размера L3).


@HadiBrais прокомментировал этот ответ некоторой информацией о процессорах AMD.

Вместо того, чтобы ограничивать загрязнение за счет выборки только в один из путей кэш-памяти, по-видимому, AMD выделяет строки, извлеченные с помощью предварительной выборки NT, с пометкой быстрого вытеснения. Вероятно, это означает размещение в позиции LRU вместо позиции «самое последнее использованное». Таким образом, следующее выделение в этом наборе кеша вытеснит строку.


Сноска 1: prefetchNTA из памяти WC, я думаю, выполняет предварительную выборку в LFB (Line Fill Buffer), что позволяет SSE4.1 movntdqa загружать уже заполненный LFB. (movntdqa загружается из памяти WC по словам Intel, действительно работают, загружая данные в LFB. Вот как несколько movntdqa загрузок в одну и ту же строку кэша могут избежать нескольких фактических операций чтения DRAM или транзакций PCIe). См. также Невременные нагрузки и аппаратный предварительный выбор , они работают вместе? - нет, не аппаратная предварительная выборка.

Но учтите, что movntdqa из памяти ББ не пригодится. Он просто работает как обычная нагрузка (плюс по какой-то причине ALU uop).

person Peter Cordes    schedule 12.11.2018
comment
Вы уверены, что на SKX инструкция пропускает L3? Согласно разделу 7.3.2 руководства по оптимизации Intel? На Nehalem и более поздних версиях его можно/нужно загрузить в L3. Я думаю, что наиболее важным свойством prefetchnta является не то, на какой уровень кеша он загружается, а то, что он помечен в наборе кеша для более быстрого вытеснения. Это относится к большинству или ко всем процессорам Intel и AMD, поддерживающим данную инструкцию. Однако также важен уровень, на котором он извлекается. Но это зависит от микроархитектуры процессоров Intel и AMD. - person Hadi Brais; 13.11.2018
comment
Извлечение его в L3 является интуитивно понятным, потому что L3 намного больше, чем L1, особенно когда реальные программы могут иметь низкую частоту совпадений в предварительно выбранных строках, а задержка основной памяти относительно очень высока в современных системах. - person Hadi Brais; 13.11.2018
comment
Согласно руководству по оптимизации AMD для семейства 17h, раздел 2.6.4, prefetchnta извлекает строку в L2 с пометкой быстрого вытеснения. Но старые процессоры AMD, как и некоторые старые процессоры Intel, попадают в L1. - person Hadi Brais; 13.11.2018
comment
В общем, в любом процессоре с инклюзивным L3 он должен быть как минимум в L3. Но он также может попасть в L1, но не в L2, или в L2, но не в L1. - person Hadi Brais; 13.11.2018
comment
Третье потенциальное свойство prefetchnta (кроме быстрого вытеснения и выборочного заполнения уровня кэша) заключается в том, что предварительно выбранная строка не может быть записана обратно на другой уровень кэша (L3). Это поведение обсуждается в руководстве AMD, но не в руководстве Intel. - person Hadi Brais; 13.11.2018
comment
@HadiBrais: мой источник поведения SKX при пропуске L3: Поддерживают ли современные архитектуры x86 временные загрузки (из обычной памяти)?. SKX изменил кеш L3: он стал меньше и больше не является инклюзивным. - person Peter Cordes; 13.11.2018
comment
@PeterCordes, так что, если в моей системе есть неинклюзивный кеш L3, но инклюзивный кеш L2, предварительная выборка nta будет выполнять предварительную выборку данных непосредственно в кеше L2, верно? - person Abhishek Nikam; 13.11.2018
comment
@AbhishekNikam: У вас процессор AMD? Intel не производит процессоры с инклюзивным L2, обычно это не инклюзивный неэксклюзивный. - person Peter Cordes; 13.11.2018
comment
Нет, @PeterCordes, это было гипотетическое утверждение, просто чтобы убедиться, что я точно понимаю, что делает prefetchnta. - person Abhishek Nikam; 13.11.2018
comment
@AbhishekNikam: о, на бумаге нет никакой гарантии, что именно он делает. Все, что вы получаете, это то, что говорит felixcloutier.com/x86/PREFETCHh.html: NTA (не- временные данные по отношению ко всем уровням кэша) — предварительная выборка данных в структуру невременного кэша и в местоположение, близкое к процессору, сводя к минимуму загрязнение кэша. То, как конкретная микроархитектура ЦП решит реализовать это, полностью зависит от архитекторов. По-видимому, AMD сделала значительно иной выбор, чем Intel; использование маркировки быстрого выселения вместо ограничения одним способом. (Возможно выделение в положении LRU) - person Peter Cordes; 13.11.2018
comment
Что касается выборки в L1, согласно разделу 7.3.2, это происходит только на процессорах, отличных от Xeon (как вы сказали, пропускает L2 и загружает в L3 и L1 с быстрой заменой). Но на процессорах Xeon строка загружается только в L3 (с быстрой заменой), а не в L1 или L2. - person Hadi Brais; 13.11.2018
comment
Да, в этом есть смысл, prefetchnta следует использовать, когда мы хотим избежать промахов в кеше, а также несколько раз использовать кэшированные данные. Реализация полностью зависит от поставщика. - person Abhishek Nikam; 13.11.2018
comment
Разве SKX не относится к категории серверных (Xeon) процессоров? В этом случае я думаю, что ответ Би, который вы связали, противоречит разделу 7.3.2. Би, кажется, не уверен (из формулировки в ответе), что L3 пропущен на SKX. Хотя инструкция может ошибаться. - person Hadi Brais; 13.11.2018
comment
Из руководства: Процессоры Intel Xeon на базе микроархитектур Nehalem, Westmere, Sandy Bridge и более новых: должны загружаться в кэш 3-го уровня с быстрой заменой. - person Hadi Brais; 13.11.2018
comment
@HadiBrais: Да, SKX = Skylake-SP = Skylake-AVX512. Руководство устарело. Эксперименты Mysticial на его SKX показали, что вы получаете промах L3, если данные вытесняются из L1d до того, как вы успеете загрузить их по требованию, в отличие от более ранних процессоров, где вы получите попадание в L3. Как правильно использовать инструкции предварительной выборки?. Это имеет смысл, потому что L3 SKX больше не является инклюзивным. - person Peter Cordes; 13.11.2018
comment
В комментарии Mysticial не говорится, что строка не будет заполнена в L3 на SKX. Он просто говорит, что если он был вытеснен до использования, он будет вытеснен со всех уровней кэша. Кажется, это говорит о том, что он загружается на все уровни кеша, что звучит неправильно. В самой последней версии мануала написано, что на процессорах Xeon строка должна быть заполнена в L3 с быстрой заменой, но остается неясным, заполняется ли она в L1 или L2. Да, L3 не является инклюзивным, но это не обязательно означает, что руководство неверно или устарело. - person Hadi Brais; 13.11.2018
comment
Если я что-то не упустил, я не вижу никого, кто говорит, что мои эксперименты подтверждают, что L3 пропускается на SKX, и я думаю, что руководство может быть правильным. Кстати, комментарий Mysticial не противоречит руководству. - person Hadi Brais; 13.11.2018
comment
@HadiBrais: При повторном прочтении того, что я связал, да, это не так ясно. Может быть, где-то было другое обсуждение с более определенными результатами / лучшими доказательствами моей интерпретации данных, которые я помнил. Например, вневременные загрузки и аппаратная предварительная выборка, работают ли они вместе?. Я все еще думаю, что SKX вообще не выделяет в L3 наиболее вероятную интерпретацию данных, но я согласен, что возможно и другое. - person Peter Cordes; 13.11.2018
comment
Я так понимаю, что на всех процессорах Xeon, начиная с Nehalem, строка обязательно будет подбираться в L3 с быстрой заменой, но может быть или не быть подтягиваться в L1 или L2 (кстати, решение может приниматься динамически). На самом деле, комментарии Mysticial не говорят однозначно, на каком уровне (уровнях) заполняется линия. Надеюсь, он увидит эти комментарии и разъяснит. - person Hadi Brais; 13.11.2018
comment
Если у вас есть SKX, мы можем легко проверить это следующим образом. Сначала отключите все предварительные выборки, выполните clflush для определенной строки кэша, выполните пустой цикл примерно на 20 000 итераций, затем выполните prefetchnta для той же строки, затем выполните тот же цикл, затем используйте загрузку по запросу для доступа к той же строке и измерьте задержка доступа. Это сообщит нам ближайший уровень кеша, на котором строка была заполнена. Затем перенесите поток на другое физическое ядро ​​и выполните загрузку по запросу на ту же линию и измерьте эту задержку. Мы можем сравнить эту задержку с задержкой L3 и... - person Hadi Brais; 14.11.2018
comment
... к задержкам между кэшем или основной памятью (для их измерения можно использовать инструмент Intel Memory Latency Checker). Если она была близка к латентности L3, то линия заполнялась в L3. Если она была близка к латентности C2C или латентности основной памяти, то линия находилась не в L3. Этот тест позволил бы нам окончательно определить, была ли линия заполнена в L3 и/или L1. - person Hadi Brais; 14.11.2018
comment
@PeterCordes что означает LFB - person zerocool; 01.12.2020
comment
@zerocool: буфер заполнения строки. Поиск в Google по запросу x86 lfb находит много полезного. Но спасибо, что указали, что я пропустил определение аббревиатуры, обычно я пытаюсь это сделать. Обновлено. - person Peter Cordes; 01.12.2020
comment
@PeterCordes знаете ли вы какой-либо способ предварительной выборки блока кода в L1 icache? - person Noah; 18.06.2021
comment
@Noah: Есть несколько способов, но, возможно, они бесполезны для общей производительности. (Но, возможно, для создания условий для микробенчмарков, как в Перенос кода в кэш инструкций L1 без его выполнения - см. мои 2 ответа там). Ответы на вопрос Как выполнить предварительную выборку редко используемого кода? в лучшем случае могут поместить код в кеш L2. (И заправьте dTLB, а не iTLB.) - person Peter Cordes; 18.06.2021