Когда две карты хуже одной: утечка памяти в llama.cpp SYCL
Вы собрали систему с двумя Intel Arc, чтобы загрузить модель побольше. Запустили llama.cpp с SYCL бэкендом. Все работает, токены генерируются. А через час система начинает тормозить, а потом вообще зависает. OOM killer убивает процесс. Оперативная память исчерпана до последнего мегабайта. Знакомо? Это классическая утечка системной памяти в llama.cpp при использовании двух видеокарт Intel Arc через SYCL.
Почему так происходит? SYCL бэкенд для Intel GPU в llama.cpp до сих пор (на 2026 год) имеет баг при многопроцессорном выполнении. Память, выделенная для обмена между устройствами, не освобождается должным образом. Каждый запрос, каждый батч - и несколько мегабайт остаются висеть в оперативке. Через час-два у вас нет памяти для чего-либо еще.
Если вы думали, что купив вторую Arc, вы получите стабильную работу - вы не одиноки. Многие пользователи столкнулись с этим, и некоторые даже написали об этом в наших статьях, например, в разборе проблем Intel Arc для LLM. Но решение есть, и оно не требует переписывания кода.
1 Диагностика: точно ли это та утечка?
Сначала убедимся, что проблема именно в утечке памяти от SYCL. Запустите llama.cpp с двумя картами и мониторьте память.
# В одном терминале запускаем модель с использованием двух GPU
./main -m ./models/qwen3-coder-next-32b-instruct-q8_0.gguf -n 512 --threads 16 --gpu-layers 50 --split-mode layer --main-gpu 0 --tensor-split 0.5,0.5 -s 42
# В другом терминале следим за памятью
watch -n 1 "free -h && echo '---' && nvidia-smi || clinfo"
Если видите, что использование оперативной памяти (RAM) постоянно растет, даже когда модель уже загружена и идет генерация, - это оно. VRAM при этом может быть стабильной.
Утечка может составлять от 10 МБ до 100 МБ в минуту. Не много, но за несколько часов складывается.
2 Обновляем все до последних версий
Первое, что нужно сделать - обновить драйверы Intel GPU. На апрель 2026 года актуальны драйверы версии 2.x или выше. Проверьте на сайте Intel.
Затем обновите oneAPI. SYCL бэкенд llama.cpp зависит от oneAPI Runtime. Убедитесь, что у вас установлен Intel oneAPI Base Toolkit и Intel oneAPI HPC Toolkit последних версий.
# Для Ubuntu/Debian
sudo apt update
sudo apt install intel-basekit intel-hpckit
# Или следуйте официальным инструкциям Intel
Теперь llama.cpp. Берите самую свежую версию из репозитория. Баги фиксят постоянно. Используйте main ветку.
cd ~/llama.cpp
git pull origin main
make clean
make -j LLAMA_SYCL=1 SYCL_TARGET=SPIR64
3 Настраиваем переменные окружения SYCL
Ключевой момент - заставить SYCL правильно управлять памятью. Выставьте эти переменные перед запуском llama.cpp.
export SYCL_CACHE_PERSISTENT=1
export SYCL_CACHE_DIR=/tmp/sycl_cache
export SYCL_DEVICE_FILTER=opencl:gpu
export SYCL_PI_TRACE=1
export SYCL_PRINT_EXECUTION_GRAPH=0
Что они делают?
- SYCL_CACHE_PERSISTENT=1 - включает кеширование компилированных ядер, что снижает нагрузку на память при повторных запусках.
- SYCL_CACHE_DIR - задает директорию для кеша. Убедитесь, что она существует и на диске есть место.
- SYCL_DEVICE_FILTER=opencl:gpu - явно указываем использовать OpenCL бэкенд для GPU. Иногда SYCL пытается использовать host device, что приводит к утечкам.
- SYCL_PI_TRACE=1 - включает отладку, но может замедлить работу. Для диагностики полезно, для продакшена можно отключить.
Эти переменные могут значительно уменьшить утечку, но не всегда полностью ее устраняют. Особенно важна первая.
4 Правильные флаги запуска llama.cpp
Сам запуск тоже нужно настроить. Вот пример команды для двух карт:
./main -m ./model.gguf \
-n 512 \
--threads 16 \
--gpu-layers 50 \
--split-mode layer \
--main-gpu 0 \
--tensor-split 0.5,0.5 \
-s 42 \
--no-mmap \
--mlock
Обратите внимание на флаги:
- --split-mode layer - распределение по слоям между GPU. Для SYCL это стабильнее, чем tensor split, особенно после фиксов в 2025 году.
- --tensor-split 0.5,0.5 - все равно нужно, но с layer split оно работает иначе. Указывает долю нагрузки на каждую карту.
- --no-mmap - отключает memory mapping файла модели. Это снижает утечку, но увеличивает время загрузки модели в память.
- --mlock - блокирует модель в RAM, предотвращая ее выгрузку в swap. Необязательно, но может помочь в системах с малым объемом оперативки.
Экспериментируйте с --gpu-layers. Чем больше слоев на GPU, тем больше памяти используется. Но если положить слишком много, утечка может усилиться. Начните с 50 для 32B моделей.
Для моделей с большим контекстом попробуйте уменьшить --batch-size и --ubatch-size. По умолчанию они автоматические, но явное указание может помочь. Например:
--batch-size 512 --ubatch-size 512
Не используйте --ngl вместо --gpu-layers. В SYCL бэкенде это может привести к еще большим утечкам. Всегда указывайте явно количество слоев для GPU. И не путайте с флагами для CUDA или Vulkan бэкендов.
5 Мониторинг и автоматический перезапуск
Даже с настройками утечка может оставаться, но значительно медленнее. Установите мониторинг и автоматический перезапуск перед критическим исчерпанием памяти. Это костыль, но он работает. Лучше, чем зависшая система.
Простой скрипт на bash:
#!/bin/bash
MODEL_PATH="./model.gguf"
LOG_FILE="./llama.log"
MIN_FREE_MEMORY_MB=2048
while true; do
# Проверяем свободную оперативную память
FREE_MEM=$(free -m | awk '/^Mem:/{print $4}')
if [ $FREE_MEM -lt $MIN_FREE_MEMORY_MB ]; then
echo "Мало памяти, перезапуск..." >> $LOG_FILE
pkill -f "./main"
sleep 10
fi
# Запускаем llama.cpp с нашими настройками
./main -m $MODEL_PATH -n 512 --threads 16 --gpu-layers 50 --split-mode layer --main-gpu 0 --tensor-split 0.5,0.5 -s 42 --no-mmap >> $LOG_FILE 2>&1
# Если процесс упал, ждем перед повторным запуском
sleep 30
done
Запустите скрипт в screen или tmux. Он будет перезапускать процесс, когда свободной оперативки останется меньше 2 ГБ.
Почему это до сих пор не пофиксили?
SYCL бэкенд для llama.cpp - community-driven проект. Intel предоставляет инструменты, но интеграция с llama.cpp делается энтузиастами. Баги в управлении памятью при multi-device выполнении - сложная проблема. Частично она связана с самим oneAPI Runtime и тем, как SYCL управляет памятью между устройствами.
Если вы хотите стабильности, рассмотрите использование одной карты или переход на гибридной системы с NVIDIA. Или попробуйте Vulkan бэкенд, но для Intel Arc он менее эффективен, особенно для квантованных моделей, как мы писали в статье про ускорение Q8_0 моделей.
Альтернативы: может, не стоит мучиться?
Если утечка продолжается, рассмотрите другие варианты:
- Ollama - но у него свои проблемы с multi-GPU. См. сравнение Ollama и llama.cpp.
- Vulkan бэкенд - для Intel Arc он есть, но производительность ниже, особенно для больших моделей. Хотя для некоторых задач подойдет.
- Использование одной карты - загрузите модель, которая помещается в VRAM одной Arc. Например, 32B модель в квантовании q4_0 может поместиться в 16GB VRAM. Или купите одну более мощную карту.
Или соберите систему с AMD картами, где ROCm работает стабильнее в multi-GPU конфигурациях. Но это уже другая история.
Итог: что конкретно делать
- Обновите драйверы Intel до последней версии (2026 года) и oneAPI.
- Соберите свежую версию llama.cpp с SYCL из main ветки.
- Выставьте переменные окружения SYCL_CACHE_PERSISTENT=1 и SYCL_DEVICE_FILTER=opencl:gpu.
- Запускайте с --split-mode layer --no-mmap и явным --tensor-split 0.5,0.5.
- Мониторьте память и при необходимости используйте скрипт перезапуска.
Эти шаги снизят утечку до приемлемого уровня. Вы сможете работать часами без перезагрузки. Но помните: dual Intel Arc с SYCL - все еще экстремальная конфигурация. Если вы только планируете покупку железа для LLM, прочтите наш разбор Intel Arc Pro B60. Там есть нюансы, которые сэкономят вам нервы.
И последнее: если все это кажется слишком сложным, может, стоит подождать, пока Intel и сообщество finally починят SYCL. А пока - удачи. И да пребудет с вами память (оперативная).