Какова цель встроенных _mm_clevict и соответствующих инструкций clevict0, clevict1?

# #x86 #intel #cpu-cache #instructions #xeon-phi

Вопрос:

В руководстве по встроенным компонентам Intel® говорится о _mm_clevict :

 void _mm_clevict (const void * ptr, int level)
#include <immintrin.h>
Instruction: clevict0 m8
             clevict1 m8
CPUID Flags: KNCNI
 

Удаляет строку кэша, содержащую адрес ptr , с уровня кэша level (может быть 0 или 1).

Какова может быть цель этой операции? Отличается ли это от _mm_cldemote ?

Ответ №1:

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

Идея (1): Это могло быть связано с конфликтами банка памяти при грязных выселениях. Например, подумайте, что произойдет, если сопоставление адресов сделает слишком вероятным, что загружаемый новый элемент будет находиться в банке DRAM, который конфликтовал с жертвой, которую нужно выбросить. Если на контроллере памяти недостаточно буферов записи, возможно, потребуется выполнить обратную запись в DRAM, прежде чем DRAM сможет переключить банки для обслуживания чтения. (Более новые процессоры имеют множество буферов записи в контроллере памяти, так что это не проблема, но это могло быть проблемой для KNC.)

Идея (2): Другая возможность заключается в том, что обработка жертвы кэша может задержать чтение нового значения из-за сериализации в каталогах дубликатов тегов (DTD). Протокол согласованности явно был немного «взломан» (чтобы Intel могла использовать существующий P54C с минимальными изменениями), но предоставленной Intel документации высокого уровня было недостаточно, чтобы понять последствия для производительности некоторых деталей реализации.

Инструкции CLEVICT были «локальными» — только ядро, выполняющее инструкцию, выполняло выселение. Грязные строки кэша будут записаны и локально признаны недействительными, но запрос на аннулирование не будет передан другим ядрам. Документация по архитектуре набора инструкций не комментирует, приводит ли инструкция CLEVICT к сообщению об обновлении от ядра к DTD. (Это было бы необходимо для идеи (2), чтобы внести какие-либо изменения в производительность.)

Инструкция CLDEMOTE, по-видимому, предназначена для уменьшения задержки при передаче данных из кэша в кэш в ситуациях между производителем и потребителем. Из описания инструкции: «Это может ускорить последующие обращения к строке другими ядрами в том же домене согласованности, особенно если строка была написана ядром, которое понижает строку». Это очень похоже на мой патент https://patents.google.com/patent/US8099557B2/ «Push для обмена инструкциями» (разработан, когда я работал в AMD).

Ответ №2:

Обратите внимание, что это KNCNI, новые инструкции Knight’s Corner, так что это вычислительные карты Xeon Phi первого поколения, до Приземления Рыцаря. Это произошло из графического процессора, так что, возможно, неудивительно, что у вас есть инструкции по управлению кэшем.

Возможно, это также имеет значение для взаимодействия с хост-системой, поскольку кэши вычислительной карты не согласованы с процессорами хост-системы. Хотя они могут быть согласованы с доступом PCIe к памяти устройства, так же, как x86 в целом имеет согласованный с кэшем DMA. (Кроме того, удаление только с одного уровня кэша все равно может оставить грязные данные на другом, если внешний кэш не включен. Если бы требовалась какая-либо ручная согласованность перед чтением хостом памяти устройства, скорее clflush всего, было бы использовано что-то другое.)

Я точно не знаю, почему он был у KNC, но нет никаких оснований ожидать, что он когда-либо появится в основных процессорах x86. Даже в KNL не было KNCNI; вместо этого в KNL есть AVX-512F ER PF; KNCNI был полным тупиковым расширением набора инструкций, которого нет ни в одном из более поздних процессоров.


Это вполне может быть аналогичной идеей cldemote при использовании с грязными данными, но с чистыми данными это позволит вам удалить данные после того, как вы закончите их читать. (Напомним, что KNC был полностью в порядке, на основе микроархитектуры P54C (Pentium) с двойным выпуском в порядке, так что вы действительно можете знать с точки зрения порядка программ, когда вы закончите доступ к строке кэша. В отличие от KNL, который был основан на Silvermont.)

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

Комментарии:

1. Это связано с KNCNI флагом CPUID; множество других также находятся под теми же флагами, не ожидается ли, что все они будут доступны для основного процессора?

2. @AlexGuteniev: Правильно, KNCNI-это тупиковое расширение. Он включает в себя целый 512-битный набор инструкций SIMD, который работал несколько иначе, чем AVX-512F, который был представлен в следующем поколении Xeon Phi, KNL. IIRC, KNCNI использует коды операций, которые другие расширения используют для других целей, в том числе, я думаю, AVX-512. Векторное расширение KNC имело ту замечательную особенность,что операции reg, reg могли иметь встроенную в исходный операнд функцию перемешивания, вроде того, как инструкции ARM могут запускать исходный операнд через переключатель стволов. AVX-512F вместо этого позволяет передавать операнды источника памяти.

3. Отредактировал свой ответ, чтобы сказать это; Я забыл, что это не часть фоновых знаний, которые я должен предположить 😛

4. Я просто случайно зашел _mm_clevict . Теперь я вижу, что встроенные функции только для KNCNI недоступны даже в <immintrin.h> том, что поставляется с Visual Studio 2022, и, скорее всего, они никогда не поддерживались MSVC

5. @AlexGuteniev: clevict Ни в каталоге включения GCC11.1, ни /usr/include в моем Arch GNU/Linux нигде нет. Интересно, поддерживал ли когда-либо эти встроенные функции какой-либо компилятор, кроме ICC, и поддерживает ли их какой-либо основной ассемблер? NASM 2.15.05 не распознает clevict0 1 мнемонику или.