Натали Фок (Natalie Vock) из команды Valve, работающая над открытым Vulkan-драйвером RADV для видеокарт AMD, подготовила набор патчей для ядра Linux и пользовательских утилит. Патчи решают давнюю проблему: на видеокартах с 8 ГБ видеопамяти и менее ядро вытесняет данные игры в медленную системную память, хотя видеопамять занята фоновыми приложениями — браузерами, мессенджерами и прочими программами. Готовое решение уже доступно в CachyOS, а в перспективе должно войти в основное ядро и другие дистрибутивы.
В чём проблема: видеопамять заканчивается не на то
На типичном рабочем столе Linux видеокарту использует не только игра. Браузер с десятком вкладок, мессенджеры на базе Electron, композитор рабочего окружения — все они занимают видеопамять. На системе автора патчей фоновые приложения съедали около 2 ГБ из 8 ГБ доступной видеопамяти ещё до запуска игры.
Когда видеопамять заканчивается, ядро переносит часть данных в область GTT (Graphics Translation Table) — участок оперативной памяти, доступный видеокарте через шину PCI Express. Пропускная способность этого канала на порядок ниже: вместо 256 ГБ/с у видеопамяти — не более 16 ГБ/с через шину. Задержки тоже значительно выше. В результате игра теряет производительность, появляются рывки и подвисания.
Ключевая проблема в том, что ядро не различает, кому принадлежат данные в видеопамяти. Для него все буферы одинаковы — не важно, хранит ли буфер текстуру из Cyberpunk 2077 или статичную картинку из фоновой вкладки браузера. Из-за этого при нехватке места вытесняются данные игры, а не фоновых приложений.
GTT (Graphics Translation Table) — область оперативной памяти системы, к которой видеокарта обращается через шину PCI Express. Некоторые игры сознательно размещают в GTT часть данных, но при нехватке видеопамяти туда попадают и те аллокации, которым место в быстрой видеопамяти.
Почему старые подходы не работали
Проблема вытеснения видеопамяти существует давно, и разработчики ядра пробовали разные решения. Первый подход был простым: при отправке команды на видеокарту драйвер перемещал нужные данные обратно в видеопамять. На практике два конкурирующих приложения по очереди вытесняли друг друга, и данные постоянно перемещались туда-обратно — это было медленнее, чем если бы данные вообще не перемещались.
Второй подход — ограничение скорости перемещений. Ядро прекращало двигать данные после достижения определённого лимита за единицу времени. Циклическое перемещение это не устранило, зато добавило рывки: драйвер то активно двигал память, то останавливался.
Третий и текущий подход: при запросе видеопамяти драйвер указывает два возможных домена — видеопамять и GTT. Если места в видеопамяти нет, аллокация сразу попадает в GTT без попытки вытеснить что-то другое. Циклические перемещения прекратились, но возникла обратная проблема: новые данные игры попадают в медленную память, хотя видеопамять занята малоценными фоновыми буферами.
Решение: контроллер dmem cgroup
Механизм cgroup в ядре Linux позволяет группировать процессы и управлять их доступом к ресурсам — процессорному времени, оперативной памяти и другим. Рабочие окружения вроде KDE Plasma уже запускают каждое приложение в собственной cgroup через systemd.
На базе этого механизма Maarten Lankhorst из Intel, Maxime Ripard из Red Hat и Натали Фок разработали контроллер dmem (device memory) для cgroup. Контроллер вошёл в основное ядро Linux начиная с версии 6.14 и позволяет назначать «защиту памяти» для конкретных групп процессов. Пока использование видеопамяти cgroup-ой ниже установленного лимита защиты, ядро не станет вытеснять её данные — вместо этого найдёт буферы менее приоритетной группы.
Однако одного контроллера dmem cgroup недостаточно. Дополнительные патчи Натали Фок исправляют поведение менеджера памяти TTM в драйвере amdgpu: без них защита не распространяется на «мгновенные вытеснения» — ситуации, когда новая аллокация при заполненной видеопамяти сразу направляется в GTT. Именно этот сценарий встречается в играх чаще всего.
cgroup (control group) — механизм ядра Linux для группировки процессов и управления их доступом к системным ресурсам: процессорному времени, оперативной памяти, вводу-выводу. Каждое приложение рабочего стола запускается в отдельной cgroup, что позволяет ядру различать приоритеты программ.
Утилиты для пользовательского пространства
Для полноценной работы нужны два пакета. Первый — dmemcg-booster — служба systemd, которая активирует контроллер dmem в иерархии cgroup и настраивает параметры защиты. Утилита работает «за спиной» systemd: после того как systemd строит иерархию cgroup, dmemcg-booster дополнительно включает в ней контроллер dmem. Это временное решение — в будущем поддержка dmem должна появиться непосредственно в systemd.
Второй пакет — plasma-foreground-booster — компонент KDE Plasma, который отслеживает, какое приложение находится на переднем плане, и назначает ему максимальный приоритет видеопамяти через cgroup. Изначально утилита ForegroundBooster в KDE Plasma управляла только приоритетом процессорного времени, а Натали Фок дополнила её поддержкой видеопамяти.
Пользователи других рабочих окружений могут использовать Gamescope — композитор Valve. Новые версии Gamescope тоже умеют выставлять приоритет видеопамяти через dmem cgroup. Утилита dmemcg-booster нужна в любом случае. Все пользовательские утилиты жёстко зависят от systemd.
Как попробовать
Проще всего — установить CachyOS с рабочим окружением KDE Plasma. Ядро CachyOS начиная с версии 7.0rc7-2 уже включает нужные патчи, а пакеты dmemcg-booster и plasma-foreground-booster доступны в репозиториях дистрибутива.
На других дистрибутивах на базе Arch Linux оба пакета доступны в AUR (plasma-foreground-booster-dmemcg). Для ядра можно использовать пакет ядра CachyOS из их репозитория, собрать ядро самостоятельно из ветки linux-dmemcg в AUR или наложить шесть отдельных патчей на исходники ядра вручную.
На дистрибутивах за пределами экосистемы Arch пока придётся подождать — со временем патчи должны войти в основную ветку ядра и быть подхвачены другими дистрибутивами.
Результат
В тесте Натали Фок на видеокарте с 8 ГБ видеопамяти одновременно с множеством фоновых приложений была запущена Cyberpunk 2077 с высокими настройками графики. Без патчей часть аллокаций игры попадала в GTT: объём данных игры в системной памяти превышал 650 МБ, хотя сама игра сознательно размещает там ровно столько. С патчами в GTT осталось только 650 МБ — именно те данные, которые игра сама размещает в системной памяти. Ни одна аллокация не была вытеснена из видеопамяти.
На практике это означает, что на видеокартах с 8 ГБ видеопамяти производительность в играх перестаёт деградировать со временем. Без патчей по мере игры всё больше данных вытесняется в медленную память, и частота кадров постепенно падает. С патчами игра получает практически весь объём видеопамяти, пока сама не превысит доступный лимит.
Заключение
Патчи Натали Фок устраняют фундаментальный недостаток управления видеопамятью в Linux: ядро впервые получает возможность отдавать приоритет активной игре, а не случайному фоновому процессу. Для владельцев видеокарт с 8 ГБ видеопамяти — а это большинство популярных моделей вроде GeForce RTX 4060 и Radeon RX 7600 — разница будет ощутимой. Пока решение ограничено CachyOS и Arch-дистрибутивами, но по мере включения патчей в основное ядро и systemd оно станет доступно повсеместно.