Расширители памяти на CXL добавили узлам терабайты за пределами процессора, и вместе с ними появился новый участник борьбы за полосу. Память за CXL медленнее локальной, её путь проходит через линию, корневой порт и порой коммутатор, и без управления эта полоса достаётся тому, кто первым занял дорогу. Управление полосой на CXL собирается из трёх слоёв: аппаратные лимиты, где они есть, разумное размещение данных по уровням памяти и честная топология с раскладкой по рельсам. Плюс свежие редакции спецификации добавляют в инструмент ящик сигнализацию обратного давления и телеметрию качества, и картина быстро меняется в пользу управляемости. До этих средств дотягиваются не все платформы, поэтому практическая ценность материала в обратном порядке: сначала топология и размещение, которые работают везде, затем лимиты там, где они есть, затем спецификационные средства по мере их появления в прошивках.
Разберём путь трафика и узкие места, лимиты через механизм SMBA на AMD, размещение и уровни памяти, топологию, средства качества на коммутаторах и порядок практической настройки.
Путь трафика и его узкие места
Трафик к расширителю идёт по собственной линии, и узкие места раскладываются по ней предсказуемо. Первое горлышко, сама линия на шестнадцать линий пятого поколения, дающая порядка шестидесяти гигабайт в секунду в каждую сторону, и два расширителя за одним корневым портом уже делят эту величину. Второе, корневой порт и его связи с мешем процессора, где трафик памяти конкурирует с вводом-выводом. Третье, коммутатор CXL, если устройства сидят за ним, и его восходящие линии, которые делятся между всеми подчинёнными устройствами. Раскладка этих уровней и определяет, какую полосу реально увидит приложение, и замеры на каждом уровне важнее суммы паспортных цифр устройств.
Отдельная особенность трафика памяти CXL в том, что он живёт в собственном протоколе поверх физики PCIe и не обязан делить классы трафика с обычным вводом-выводом, но физическую линию и порты делит всегда. Поэтому приоритезация ввода-вывода на тех же портах влияет на память косвенно, через занятость линии, и разруливается теми же средствами, о которых шла речь в разборе приоритезации PCIe. Конкуренция за расширитель характерна и для многофункциональных узлов: несколько виртуальных машин, использующих одну и ту же медленную память, делят одну линию без взаимных договорённостей, и их полоса зависит только от их собственного аппетита, пока кто-то не введёт правила.
Лимиты полосы через SMBA на AMD
Самый прямой механизм управления полосой CXL сегодня предлагает AMD в механизме SMBA, выделении полосы медленной памяти. Идея ровная: трафик к медленным устройствам, и прежде всего к памяти CXL, ограничивается процентом на домен кэша, и вся медленная группа душится как единое целое. В интерфейсе resctrl это отдельный ресурс со своей схемой:
mount -t resctrl resctrl /sys/fs/resctrl
mkdir /sys/fs/resctrl/p_cxl
echo "SMBA:0=50;1=50" > /sys/fs/resctrl/p_cxl/schemata
Ресурс SMBA живёт рядом с обычным MB для локальной памяти, поддерживает группы, и лимиты выставляются по доменам кэша с шагом квантования в одну восьмую гигабайта в секунду. Два ресурса работают независимо: локальная память ограничивается по одному, медленная по другому, и одна ресурсная группа может нести обе схемы одновременно, что удобно службам, читающим и локальные, и медленные страницы в одном процессе. Классическая схема применения, оградить латентную службу от соседа, который залил рабочие наборы в CXL-память: службе достаётся ресурсная группа с приличным лимитом SMBA, фоновым задачам остаток, и деградация становится управляемой, а не случайной. Цифры прикинуть легко: при полосе линии порядка шестидесяти гигабайт в секунду лимит в половину отдаёт службе гарантированные тридцать, и остаток делится между всеми, кто не попал в ограниченные группы. Логика ресурса SMBA строго централизованная: все медленные источники узла душатся как одно целое, и индивидуальные лимиты на каждое устройство этим механизмом не задаются, что важно помнить при раскладке ожиданий. На Intel-платформах аналога на момент этих строк в общем интерфейсе нет, и там управление полосой CXL сводится к размещению, топологии и средствам коммутаторов, о которых речь ниже.
Размещение как форма управления полосой
Не всякое управление полосой сводится к лимитам, и самый дешёвый рычаг, размещение. Ядро с уровнями памяти отправляет холодные страницы в CXL-память и держит горячие в локальной, и настройка этого механизма фактически управляет тем, какая доля трафика вообще идёт через медленную дорогу. Приложениям с явной раскладкой достаются привязки по узлам: буферы холодных данных на CXL-узле через numactl, горячие структуры в локальной памяти, и профиль трафика становится результатом осознанного решения, а не судьбы. Счётчики миграций страниц и соотношение локальных и удалённых обращений из статистики узлов показывают, насколько фактическая раскладка совпадает с планом, и это то же измерение, что знакомо по мониторингу полосы локальной памяти, только в разрезе уровней. Механика демоушна привязана к NUMA-балансировке: страница, к которой давно не обращались, переезжает уровнем ниже по показаниям сканирования, а обратный подъём случается при горячих обращениях. Параметры сканирования и пороги настраиваются в семействе sysctl балансировки, и агрессивность переноса прямо управляет тем, сколько трафика вообще уходит на медленную дорогу: ретивый перенос гонит туда полугорячие страницы и сжигает полосу зря.
Отдельный приём, объединение прикладных пулов: кэши приложений и временные буферы, которым полоса нужнее объёма, живут в локальной памяти, а сжатые архивы, таблицы историй и прочие холодные массивы в CXL. Так размещение решает вопрос полосы без единого лимита, и лимиты остаются для случаев, где размещение недостаточно. На многопользовательских узлах размещение работает и как инструмент справедливости: пулы пользователей привязываются к своим уровням памяти, и никто не выдавливает соседа из локальной памяти только потому, что первым занял адресное пространство.
Топология узла и раскладка по рельсам
Раскладка железа задаёт потолок до всякой настройки. Один расширитель на сокет с собственной линией даёт простую и предсказуемую картину, пара расширителей за коммутатором делит восходящую линию, и раскладка по рельсам с отдельным портом на каждое устройство стоит затрат, зато снимает конкуренцию за корневые порты. Чередование на уровне устройств и страниц, о котором подробно говорилось в разборе чередования, здесь тоже инструмент полосы: размазывание потока по устройствам собирает суммарную полосу линий, крупный шаг сохраняет локальность страниц, и выбор шага это выбор профиля полосы против предсказуемости.
Честность прошивки в этой картине критична: таблицы расстояний и характеристик памяти должны отражать реальную топологию, иначе планировщик и приложения принимают решения по ложной карте. Сверка заявленных характеристик устройств с фактическими замерами входит в приёмку узла, и расхождения всплывают именно на смешанных нагрузках, где полоса распределяется между локальной памятью, CXL и вводом-выводом одновременно. Отдельное решение на этапе сборки касается платформенного чередования между локальной и медленной памятью: даже там, где прошивка умеет смешивать уровни в однородный узел, управляемость чаще выигрывает от раздельных узлов, потому что размещение и лимиты требуют, чтобы уровни были различимы. Многохоловые устройства, доступные с нескольких сторон, добавляют ещё одну ось раскладки, и их сессии лучше разводить по независимым путям заранее, а не решать конфликт по факту.
Качество сервиса на коммутаторах и в спецификации
Коммутаторы CXL добавляют слой арбитража между устройствами и хостами, и на многохостовых конфигурациях именно они распределяют полосу восходящих линий. Реализация средств качества сервиса в прошивках на момент этих строк заметно различается между вендорами, и каждая заявленная возможность проверяется замером на целевой нагрузке, а не по строке в документе. Спецификация движется в ту же сторону: группы качества сервиса в таблицах прошивки дают устройствам и окнам памяти характеристики полосы и задержки, телеметрия свойств устройств сообщает фактические возможности, а свежие редакции добавляют сигнализацию обратного давления, при которой устройство сообщает о наполнении буферов, и эта информация призвана дотянуться до источников трафика. В таблицах характеристик устройство расписывает составляющие: собственную полосу носителя, полосу интерфейса и задержки на компонентах, и разбор этих полей отвечает на вопрос, что именно является ограничителем в конкретном устройстве. Многохоловые устройства, обслуживаемые с нескольких сторон, и вовсе превращают распределение полосы в задачу координации, и здесь коммутатор становится обязательным элементом управления, а не удобным аксессуаром.
Для администратора всё это означает постепенное появление рычагов там, где раньше оставался только топологический. Практический совет на переходный период, выбирать коммутаторы и устройства с документированными возможностями качества сервиса, если полоса под смешанной нагрузкой входит в требования, и проверять эти возможности замером, а не паспортными строками.
Замер полосы и диагностика узла
Замер полосы CXL строится из тех же кирпичей, что и любой замер памяти, с поправкой на уровни. Эталонные потоки читают и пишут буферы на CXL-узле через привязки по узлам, фиксируется полоса и задержка на одиночных запросах, затем сценарий повторяется под фоновым трафиком локальной памяти и ввода-вывода, и разница показывает реальную цену совместного пути:
numactl --membind=2 -- fio --name=cxl --rw=randread --bs=1M \
--iodepth=8 --runtime=30 --time_based --size=8G
grep -E 'pgmigrate' /proc/vmstat
Диагностика дополняет замер: счётчики миграций показывают активность уровней памяти, статистика узлов раскрывает долю удалённых обращений, а трассировочные события подсистемы CXL в журнале ядра подхватывают ошибки и события устройств. Задержку мерят отдельно от полосы: очередь глубиной один и мелкий блок дают чистое время ответа, и именно этот замер чувствителен к конкуренции за линию, тогда как большие блоки сглаживают всплески. На платформах AMD дополнительно работают счётчики фабрики данных через нецентральный PMU, показывающие трафик по каналам памяти, и в разрезе локальных и медленных каналов они дают картину распределения без приложения-нагрузчика. Сравнение с заявленными характеристиками из таблиц прошивки завершает картину, и расхождения между паспортом и фактом становятся поводом для разговора с вендором до инцидентов, а не после.
Практический порядок управления полосой
Управление полосой CXL на узле складывается в шесть шагов:
- снять фактическую топологию путей и проверить честность таблиц расстояний и характеристик замерами;
- классифицировать данные узла по температуре и развести уровни памяти, оставив локальную память горячим буферам, причём классификация опирается на пару дней мониторинга горячих страниц, а не на догадки;
- на платформах с SMBA завести ресурсные группы с лимитами для классов, конкурирующих за медленную память;
- настроить чередование и рельсы под профиль полосы, зафиксировав шаг и число путей в провижининге;
- наладить замер полосы и задержки на CXL-узлах в мониторинге с эталонными прогонами до и после правок;
- следить за развитием средств качества сервиса на коммутаторах и в прошивках и закладывать их в закупки.
Итог у управления полосой CXL переходный, но рабочий уже сейчас, и переходность здесь не приговор: половина инструментов из этого материала про размещение и топологию переживёт любые редакции спецификации. Лимиты на AMD дают прямой рычаг там, где он нужен больше всего, размещение и топология закрывают остальное на любой платформе, а спецификация и коммутаторы двигаются в сторону полноценного качества сервиса. Узел, на котором полоса медленной памяти измерена, ограничена и задокументирована, превращает CXL из лотереи в предсказуемый уровень памяти с ясной ценой, и именно так эта технология и должна жить в продакшене.