Когда 8 ГБ VRAM - это не смешно
Ты купил новый ноутбук с AMD Strix Halo. 32 ядра, 40 CU iGPU - на бумаге монстр. Запускаешь свою 120B модель через llama.cpp с ROCm и получаешь любимую ошибку: 'Unable to allocate ROCm0 buffer'. Знакомо? Поздравляю, ты уперся в лимит GTT.
GTT по умолчанию выделяет всего 4-8 ГБ под iGPU. Даже если у тебя 128 ГБ оперативки. Это архитектурное ограничение, а не баг.
Что такое GTT и почему он тебя душит
Graphics Translation Table - это таблица трансляции, через которую GPU обращается к системной памяти. Представь ее как адресную книжку. По умолчанию в этой книжке всего 8 страниц (ГБ). Хочешь записать больше адресов - нужна больше книжка.
Для дискретных карт это не проблема - у них своя видеопамять. Но iGPU использует оперативную память. И когда ты пытаешься загрузить модель, которая требует 40+ ГБ (как в случае с coding агентами на 128GB RAM), система просто не может выделить столько через GTT.
1 Проверяем текущий размер GTT
Прежде чем что-то ломать, посмотрим, с чем работаем. Открой терминал и выполни:
sudo dmesg | grep -i gtt
Ищешь строку типа:
[drm] GTT: 8192M 0x0000008000000000 - 0x00000081FFFFFFFF
8192M - это 8 ГБ. Именно столько твой iGPU может использовать сейчас. Даже если у тебя 128 ГБ RAM и ты читал про инфраструктуру на домашнем железе.
2 Готовим систему к изменению
Будем менять параметры загрузки ядра. Сначала сделаем бэкап текущей конфигурации:
sudo cp /etc/default/grub /etc/default/grub.backup.$(date +%Y%m%d)
Если сломаешь загрузчик - система не запустится. Убедись, что у тебя есть Live USB с Linux для восстановления. Серьезно.
3 Меняем размер GTT на 128 ГБ
Открываем конфиг GRUB:
sudo nano /etc/default/grub
Ищем строку GRUB_CMDLINE_LINUX_DEFAULT. Она выглядит примерно так:
GRUB_CMDLINE_LINUX_DEFAULT="quiet splash"
Добавляем параметр amdgpu.gttsize=131072. Почему 131072? Потому что размер указывается в мегабайтах. 128 ГБ × 1024 = 131072 МБ.
GRUB_CMDLINE_LINUX_DEFAULT="quiet splash amdgpu.gttsize=131072"
amdgpu.dc=0 для отключения Display Core. Если у тебя проблемы с выводом изображения после перезагрузки - добавь и его.4 Применяем изменения и перезагружаемся
Обновляем конфигурацию GRUB:
sudo update-grub
Или для систем с UEFI:
sudo grub-mkconfig -o /boot/grub/grub.cfg
Перезагружаемся:
sudo reboot
5 Проверяем результат
После загрузки снова проверяем dmesg:
sudo dmesg | grep -i gtt
Теперь должно быть:
[drm] GTT: 131072M 0x0000008000000000 - 0x0000008FFFFFFFFF
Поздравляю! Твой iGPU теперь видит 128 ГБ памяти. Но это только половина дела.
Настройка ROCm для работы с огромным GTT
Теперь нужно сказать ROCm, что можно использовать всю эту память. Создаем конфигурационный файл:
sudo nano /etc/roc_env.conf
Добавляем строку:
HSA_OVERRIDE_GFX_VERSION=11.0.0
И устанавливаем переменную окружения:
echo "export HSA_OVERRIDE_GFX_VERSION=11.0.0" | sudo tee -a /etc/profile.d/roc_env.sh
GFX_VERSION зависит от твоего GPU. Для Strix Halo это обычно gfx1150 или gfx1151. Проверь через rocminfo | grep -i gfx.
Тестируем на реальной задаче
Создаем простой HIP-кернел для проверки выделения памяти:
// test_hip.cpp
#include <hip/hip_runtime.h>
#include <iostream>
#include <vector>
#define CHECK_HIP(call) \
do { \
hipError_t err = call; \
if (err != hipSuccess) { \
std::cerr << "HIP Error: " << hipGetErrorString(err) << " at " << __FILE__ << ":" << __LINE__ << std::endl; \
exit(1); \
} \
} while(0)
int main() {
size_t free, total;
CHECK_HIP(hipMemGetInfo(&free, &total));
std::cout << "Total GPU memory: " << total / (1024*1024*1024) << " GB" << std::endl;
std::cout << "Free GPU memory: " << free / (1024*1024*1024) << " GB" << std::endl;
// Пробуем выделить 100 ГБ
size_t size = 100ULL * 1024 * 1024 * 1024;
void* ptr;
hipError_t err = hipMalloc(&ptr, size);
if (err == hipSuccess) {
std::cout << "Successfully allocated 100 GB!" << std::endl;
CHECK_HIP(hipFree(ptr));
} else {
std::cout << "Failed to allocate 100 GB: " << hipGetErrorString(err) << std::endl;
}
return 0;
}
Компилируем и запускаем:
hipcc test_hip.cpp -o test_hip
./test_hip
Типичные ошибки и как их избежать
| Ошибка | Причина | Решение |
|---|---|---|
| "Failed to allocate 100 GB: hipErrorOutOfMemory" | Системная память фрагментирована | Перезагрузись и попробуй запустить тест первым делом |
| Черный экран после перезагрузки | Конфликт с Display Core | Добавь amdgpu.dc=0 к параметрам ядра |
| ROCm не видит GPU | Неправильный GFX_VERSION | Проверь через rocminfo и исправь в конфиге |
FAQ: вопросы, которые ты боялся задать
Это замедлит работу системы?
Да. Использование системной памяти как VRAM медленнее, чем выделенная видеопамять. Но когда выбираешь между "медленно" и "вообще не работает" - выбор очевиден.
Можно ли выделить больше 128 ГБ?
Теоретически да, но на практике упираешься в ограничения архитектуры. 128 ГБ - разумный максимум для текущего поколения APU.
Будет ли это работать с Vulkan?
Нет. Vulkan использует другие механизмы выделения памяти. Для Vulkan-приложений (вроде llama.cpp с Vulkan) этот метод не поможет.
А если у меня 64 ГБ оперативки?
Не выделяй больше, чем у тебя есть физической памяти. И оставь хотя бы 8-16 ГБ для системы. Формула простая: gttsize = (total_ram - 16GB) * 1024.
Что дальше?
Теперь ты можешь запускать модели, которые раньше были недоступны. Но помни: производительность будет ниже, чем на дискретной карте с HBM. Это компромисс.
Если тебе нужно еще больше памяти - посмотри как добавить второй GPU или изучи стратегии масштабирования.
И главное: не бойся экспериментировать. Самые интересные открытия происходят, когда ты заставляешь железо делать то, для чего оно не было предназначено.