Архитекторы процессоров архитектуры x86 исторически были против предоставления программистам возможности непосредственного управления кэшем. Один как-то сказал мне в 2009 году — «никогда мы этого не сделаем, кэш всегда должен быть прозрачным для программиста». Некоторые RISC процессоры представляют архитектурную возможность управления данными/кодом, который окажется в кэше. И вот, наконец-то, нечто подобное появилось и в архитектуре x86 (начиная с Broadwell*).
Два года назад я написал пост о том, что кэши первого и второго уровня не совсем эксклюзивно принадлежат каждому ядру, и что политика замещения кэш-линий в L3 кэше про принципу наиболее давнего использования ( pseudo-LRU) — прямой путь к инверсии приоритета (priority inversion). Читатели спрашивали, не существует ли какая-нибудь аппаратная фича, которая бы позволила бы побороть priority inversion, не позволяя низкоприоритетным процессам вытеснять данные из чужих кэшей первого и второго уровня, и не давая заховать бОльшую часть кэша третьего уровня.
Такая фича теперь есть, и называется CAT — Cache Allocation Technology. Тогда я не имел права описать эту фичу на хабре, так как официально она еще не была выпущена. Ее описание появилось в Intel® 64 and IA-32 Architectures Software Developer’s Manual, том 3, глава 17 часть 15, ее показали на IDF'15 в Сан Франциско, и в lkml давно идут дискуссии, какой интерфейс к CAT войдет в ядро Linux. Скорее всего интерфейс будет реализован через cgroups. Таким образом планировщик задач будет заботится о том, чтобы пользовательские задачи с определенным приоритетом получали определенную часть кэша.
Пока поддержка CAT еще не включена в ядро, можно пользоваться напрямую. В Linux все просто — вам понадобится установить msr-tools или аналог, и потом читать и писать в два MSR(Model Specific Register), используя # rdmsr, # wrmsr — да, надо быть root. Есть и более удобный интерфейс. В Windows несколько сложнее, можно пользоваться windbg, или найти/написать драйвер для rdmsr/wrmsr.
Далее я буду объснять на примере Xeon сервера о шестнадцати ядрах, 20-way L3 кэшем, по 2.5 мегабайта на ядро. Интерфейс очень простой. Есть 2 вида MSR:
IA32_L3_MASKn: Class of Service. Это битовая маска, где каждому биту соответствует way (не set!) кэша третьего уровня. Эти MSR'ы имеют номера 0xc90, 0xc91, и т.д. Их можно писать и читать с любого ядра, они общие для всех ядер каждого процессора.
И IA32_PQR_ASSOC (0xc8f): определяет текущий активный класс для каждого ядра. Этот MSR свой для каждого ядра.
По умолчанию, все битовые маски установлены в 1 (то есть 0xfffff в моем примере) на каждом процессоре, и IA32_PQR_ASSOC для каждого ярдра равна 0, так что фича неактивна.
Как видите, если использовать CAT без поддержки операционной системы, придется также вручную следить за соответствием между IA32_PQR_ASSOC для каждого ядра, и тем какие процессы/нити на нем работают.
Также возможен интересный «хак»: можно как-бы «залочить» данные (и/или код) в кэше, если сначала включить несколько way'ев, поместить туда данные, а потом исключить эту часть кэша из всех активных битовых маск. Тогда эти данные останутся в кэше (менять их, конечно, можно), и никто их не сможет вытеснить.
Существует интересный класс LLC side channel атак. Так как эти атаки пользуются измерением, в каком way находятся данные, то разделяя кэш между виртуалками без пересечений при помощи CAT, мы полностью защищаемся от этих классов атак.
Кэш, как известно, сделан ассоциативным не зря. Используюя CAT, мы снижаем ассоциативность. Если отдать какому-то ядру 1/10 кэша, получится, что у него «свой» L3 кэш в 4 мегабайта, 2-way. 4 Мегабайта — это неплохо, но вот 2-way это очень мало. Очевидно, будет много промахов по кэшу из-за нехватки ассоциативности. Этот эффект можно измерить. Несколько лет назад я написал пост, в котором подробно описал как при помощи cache coloring разделить на непересекающиеся части L3 кэш. У этой техники есть ряд недостатков, поэтому для этой цели в распространенных ОС и гипервизорах она не используется (есть несколько специализированных гипервизоров, где она используется, но я не могу их назвать в статье.)
Итак, небольшой микробенчмарк. Одно ядро гоняет STREAM, второе измеряет время доступа к кэш линиям. При помощи CAT и Cache Coloring мы делим кэш между ними на разного размера неперескающиеся области, и во втором тесте размер области данных изменяем пропорционально.

Вот результат. (По X — доля L3 второго ядра, по Y — процент промахов по кэшу на втором ядре). Признаюсь, что я точно не знаю, почему при уменьшении кэша сначала количество промахов падает (могу предположить, что это эффект, описанный в этой статье). Но начиная от 20 мегабайтов кэша 10-way, и до 4 мегабайт 2-way, очевидно, что разница в пропорции промахов по кэшу следует из уменьшения ассоциативности в случае использования CAT.
Чтобы проверить, доступна ли CAT на определенной модели процессора, есть отдельный флаг cpuid. В некоторых моделях она выключена, даже если в данном семействе CAT поддерживается. Но я предполагаю, что может найтись хакер, который обнаружит, как ее включить на любом процессоре, начиная с Haswell.
Вот и все, вкраце, что нужно знать, чтобы использовать CAT. Кроме того, CAT — часть нового семейства технологий platform quality of service, которые можно описать в отдельном посте, если интересно. Помимо CAT к ним относится CMT(Cache Monitoring Technology), которая позволяет измерять эффективность разделения общего кэша, MBM (Memory Bandwidth Monitoring), делающая то же с памятью, и CDP (Code and Data Prioritization).
Два года назад я написал пост о том, что кэши первого и второго уровня не совсем эксклюзивно принадлежат каждому ядру, и что политика замещения кэш-линий в L3 кэше про принципу наиболее давнего использования ( pseudo-LRU) — прямой путь к инверсии приоритета (priority inversion). Читатели спрашивали, не существует ли какая-нибудь аппаратная фича, которая бы позволила бы побороть priority inversion, не позволяя низкоприоритетным процессам вытеснять данные из чужих кэшей первого и второго уровня, и не давая заховать бОльшую часть кэша третьего уровня.
Такая фича теперь есть, и называется CAT — Cache Allocation Technology. Тогда я не имел права описать эту фичу на хабре, так как официально она еще не была выпущена. Ее описание появилось в Intel® 64 and IA-32 Architectures Software Developer’s Manual, том 3, глава 17 часть 15, ее показали на IDF'15 в Сан Франциско, и в lkml давно идут дискуссии, какой интерфейс к CAT войдет в ядро Linux. Скорее всего интерфейс будет реализован через cgroups. Таким образом планировщик задач будет заботится о том, чтобы пользовательские задачи с определенным приоритетом получали определенную часть кэша.
Пока поддержка CAT еще не включена в ядро, можно пользоваться напрямую. В Linux все просто — вам понадобится установить msr-tools или аналог, и потом читать и писать в два MSR(Model Specific Register), используя # rdmsr, # wrmsr — да, надо быть root. Есть и более удобный интерфейс. В Windows несколько сложнее, можно пользоваться windbg, или найти/написать драйвер для rdmsr/wrmsr.
Далее я буду объснять на примере Xeon сервера о шестнадцати ядрах, 20-way L3 кэшем, по 2.5 мегабайта на ядро. Интерфейс очень простой. Есть 2 вида MSR:
IA32_L3_MASKn: Class of Service. Это битовая маска, где каждому биту соответствует way (не set!) кэша третьего уровня. Эти MSR'ы имеют номера 0xc90, 0xc91, и т.д. Их можно писать и читать с любого ядра, они общие для всех ядер каждого процессора.
И IA32_PQR_ASSOC (0xc8f): определяет текущий активный класс для каждого ядра. Этот MSR свой для каждого ядра.
По умолчанию, все битовые маски установлены в 1 (то есть 0xfffff в моем примере) на каждом процессоре, и IA32_PQR_ASSOC для каждого ярдра равна 0, так что фича неактивна.
Как видите, если использовать CAT без поддержки операционной системы, придется также вручную следить за соответствием между IA32_PQR_ASSOC для каждого ядра, и тем какие процессы/нити на нем работают.
Также возможен интересный «хак»: можно как-бы «залочить» данные (и/или код) в кэше, если сначала включить несколько way'ев, поместить туда данные, а потом исключить эту часть кэша из всех активных битовых маск. Тогда эти данные останутся в кэше (менять их, конечно, можно), и никто их не сможет вытеснить.
Существует интересный класс LLC side channel атак. Так как эти атаки пользуются измерением, в каком way находятся данные, то разделяя кэш между виртуалками без пересечений при помощи CAT, мы полностью защищаемся от этих классов атак.
Кэш, как известно, сделан ассоциативным не зря. Используюя CAT, мы снижаем ассоциативность. Если отдать какому-то ядру 1/10 кэша, получится, что у него «свой» L3 кэш в 4 мегабайта, 2-way. 4 Мегабайта — это неплохо, но вот 2-way это очень мало. Очевидно, будет много промахов по кэшу из-за нехватки ассоциативности. Этот эффект можно измерить. Несколько лет назад я написал пост, в котором подробно описал как при помощи cache coloring разделить на непересекающиеся части L3 кэш. У этой техники есть ряд недостатков, поэтому для этой цели в распространенных ОС и гипервизорах она не используется (есть несколько специализированных гипервизоров, где она используется, но я не могу их назвать в статье.)
Итак, небольшой микробенчмарк. Одно ядро гоняет STREAM, второе измеряет время доступа к кэш линиям. При помощи CAT и Cache Coloring мы делим кэш между ними на разного размера неперескающиеся области, и во втором тесте размер области данных изменяем пропорционально.

Вот результат. (По X — доля L3 второго ядра, по Y — процент промахов по кэшу на втором ядре). Признаюсь, что я точно не знаю, почему при уменьшении кэша сначала количество промахов падает (могу предположить, что это эффект, описанный в этой статье). Но начиная от 20 мегабайтов кэша 10-way, и до 4 мегабайт 2-way, очевидно, что разница в пропорции промахов по кэшу следует из уменьшения ассоциативности в случае использования CAT.
Чтобы проверить, доступна ли CAT на определенной модели процессора, есть отдельный флаг cpuid. В некоторых моделях она выключена, даже если в данном семействе CAT поддерживается. Но я предполагаю, что может найтись хакер, который обнаружит, как ее включить на любом процессоре, начиная с Haswell.
Вот и все, вкраце, что нужно знать, чтобы использовать CAT. Кроме того, CAT — часть нового семейства технологий platform quality of service, которые можно описать в отдельном посте, если интересно. Помимо CAT к ним относится CMT(Cache Monitoring Technology), которая позволяет измерять эффективность разделения общего кэша, MBM (Memory Bandwidth Monitoring), делающая то же с памятью, и CDP (Code and Data Prioritization).
Duduka
Ведутся ли работы по созданию серверного чипа с ARM архитектурами, ответие хотяб в виде намека.
izard Автор
А зачем это Интел? Несколько лет назад появились серверные Арм, и одновременно появились сервера на Атом с соответствующим энергопотреблением.
Duduka
Соответсвующее энергопотребление — это отлично, только армы могут развиваться дальше, а у интела архитектурные энергозатраты… нет, я не спрашивал о резонах интела, я спрашивал о будущих серверных инфраструктурах, у интела есть такая возможность, но что она реализует!? Ксеоны — очевидно будут развивать, тут понятно, но они могли бы и обудущем подумать.
izard Автор
Архитектурные энергозатраты? Вы имеете в виду декодер x86 инструкций во фронтенде? Посмотрите на кристалл даже не Xeon, а Атом, и найдите сколько он по площади занимает. Лет 15 назад это еще был какой-то ощутимый %, а теперь — сотые доли % если не тысячные.
Duduka
что, вы, конечно нет, система команд, регистры, бранч-придикт, кеширование, и самое главное — simd и gpu. лет 10 назад обещали развитие разрядности в направлении 1024, 2048 бит, в рамках x86-..., что экономии энергопотребления способствовать не будет, и декодер хоть и увеличится, но не на много, вот как будут разгонять шину/шины, кеши… в рамках технологий исполнителей 50х-70х?
izard Автор
А, тогда ладно. Но бранч предикт, кэширование, simd и gpu принципиально на arm не отличается. Так что вся эта гонка за % CPI за счет небольшой оптимизации текущих боттлнеков в конвейере продолжается надолго. Есть конечно и технологии 90х а не 70х, но про них, когда/если придет время, расскажет большой босс на IDF.
beeruser
Несколько лет назад были лишь X-Gene 1, 32х-битки Marvel, Calxeda. Они достаточно тухлые — хуже Атома.
Thunder-X нацелен на специфическую нишу.
Opteron A1100 задержался на 2 года. Опять же он не создавался как «серверный» в общем смысле слова.
Так что, по сути, нет их.
Интересные штуки пока ещё только в разработке — AMD K12, 64х-ядерный Phytium MARS, Hydra от Qualcomm.
Битва ещё не началась =)
valeriyk
ведутся. только не Интелом.