Проблема: CUDA — не всегда король скорости
В мире локальных LLM сложился почти религиозный культ NVIDIA и CUDA. Большинство гайдов, бенчмарков и обсуждений вращается вокруг зеленых видеокарт. Когда речь заходит о llama.cpp — самом популярном фреймворке для запуска моделей на потребительском железе — по умолчанию выбирают бэкенд CUDA. Но наши недавние тесты показали контринтуитивный результат: для конкретных моделей, таких как GLM4 и Ministral3, бэкенд Vulkan демонстрировал стабильно более высокую скорость генерации токенов.
Это не универсальная истина. Результаты зависят от архитектуры модели, размера контекста, квантования и железа. Но сам факт, что кроссплатформенный Vulkan может обогнать "родную" CUDA на картах NVIDIA, заслуживает глубокого разбора.
Гипотеза: почему Vulkan может быть быстрее?
Чтобы понять феномен, нужно заглянуть под капот llama.cpp и самих бэкендов.
- Уровень абстракции: CUDA — высокоуровневый фреймворк с большим количеством "магии" и автоматической оптимизацией. Vulkan — низкоуровневый API, дающий разработчикам прямой контроль над памятью, очередями команд и синхронизацией. В умелых руках (как у разработчиков llama.cpp) это позволяет выжать больше из железа для специфичных паттернов вычислений в трансформерах.
- Эффективность памяти: Некоторые модели, особенно с нестандартной архитектурой (как GLM4), могут иметь паттерны доступа к памяти, которые Vulkan-реализация в llama.cpp обрабатывает эффективнее. Это может снижать задержки при передаче данных между CPU и GPU.
- Наложение вычислений и передачи данных: Низкоуровневый контроль Vulkan позволяет лучше организовать асинхронное выполнение, когда покуда одна часть ядра GPU вычисляет, другая уже загружает следующие данные.
- "Чистота" кода ядер: Реализация CUDA в llama.cpp исторически развивалась дольше и может нести legacy-код. Vulkan-бэкенд писался с нуля под современные требования, возможно, с более оптимальными алгоритмами для определенных операций (например, RoPE или внимания).
Бенчмарк: цифры говорят сами за себя
Мы провели тесты на системе: RTX 4070 Super, Ryzen 7 7800X3D, 64 ГБ DDR5, Ubuntu 24.04, драйверы NVIDIA 560. Использовалась последняя версия llama.cpp из мастера (коммит от ~01.2025).
| Модель (Квант.) | Бэкенд | Скорость (токен/с) предзаполнение | Скорость (токен/с) генерация | Пик VRAM |
|---|---|---|---|---|
| GLM4-9B-Chat (Q4_K_M) | CUDA | 112 | 45 | 6.8 ГБ |
| GLM4-9B-Chat (Q4_K_M) | Vulkan | 128 (+14%) | 52 (+16%) | 6.5 ГБ |
| Ministral-3B (Q4_K_S) | CUDA | 285 | 118 | 2.9 ГБ |
| Ministral-3B (Q4_K_S) | Vulkan | 310 (+9%) | 130 (+10%) | 2.7 ГБ |
Прирост в 10-16% — это не погрешность, а существенная разница, особенно при длинных сессиях генерации. Интересно, что Vulkan также показал чуть более низкое потребление VRAM.
Пошаговый план: как протестировать и перейти на Vulkan
1 Сборка llama.cpp с поддержкой Vulkan
Убедитесь, что у вас установлены Vulkan SDK и драйверы. Для NVIDIA это обычно пакет libvulkan1 и nvidia-vulkan-common.
git clone https://github.com/ggerganov/llama.cpp
cd llama.cpp
# Ключевой момент: активируем поддержку Vulkan
mkdir build && cd build
cmake .. -DLLAMA_VULKAN=ON -DCMAKE_BUILD_TYPE=Release
make -j$(nproc)
2 Запуск модели с Vulkan-бэкендом
Используйте флаг -ngl (или --n-gpu-layers) для оффлоада слоев на GPU и укажите Vulkan через -bk или переменную окружения.
# Способ 1: Через флаг в main
./main -m ./models/glm4-9b-chat-q4_k_m.gguf -p "Hello, AI" -n 512 -ngl 99 -bk vulkan
# Способ 2: Через переменную окружения (удобно для server)
GGML_BACKEND=vulkan ./server -m ./models/ministral-3b-q4_k_s.gguf -c 2048 --port 8080 -ngl 99
3 Проведение собственного бенчмарка
Сравните производительность для вашей конкретной модели и железа. Используйте скрипт или просто замерьте время.
# Простой бенчмарк-скрипт
#!/bin/bash
MODEL="./models/your-model.gguf"
PROMPT="Repeat after me: AI performance testing"
for BACKEND in cuda vulkan; do
echo "=== Testing $BACKEND ==="
time GGML_BACKEND=$BACKEND ./main -m $MODEL -p "$PROMPT" -n 256 -ngl 99 -t 8 --silent-prompt 2>&1 | tail -5
echo
sleep 5 # Охлаждение
done
Нюансы и возможные ошибки
Не все функции llama.cpp одинаково хорошо реализованы в Vulkan. Например, сложные sampling-методы (как mirostat) или работа с очень большим контекстом (32K+) могут вести себя стабильнее в CUDA. Всегда тестируйте.
- Ошибка: "ggml_vulkan_init: failed to create instance". Решение: Установите Vulkan SDK и убедитесь, что
vulkaninfoработает. На некоторых Linux-дистрибутивах нужны пакетыvulkan-toolsиmesa-vulkan-drivers(или проприетарные драйверы NVIDIA с поддержкой Vulkan). - Падение производительности при многопоточной загрузке слоев. Vulkan-бэкенд может быть чувствителен к параметру
-t(количество CPU-тредов). Иногда значение по умолчанию или-t 8работает лучше, чем максимальное. - Нестабильность с некоторыми квантованиями. Экзотические квантования (например, IQ4_XS) в первую очередь тестируются на CUDA. Используйте проверенные Q4_K_M, Q5_K_M.
Если вы работаете с несколькими видеокартами, особенно разными (например, NVIDIA + AMD), стратегия распределения слоев через Vulkan может оказаться более гибкой, чем через CUDA. В этом случае стоит изучить наш гайд про масштабирование локальных LLM.
FAQ: ответы на частые вопросы
Это работает только на картах NVIDIA?
Нет, Vulkan — кроссплатформенный API. Прирост может наблюдаться и на AMD, и на Intel Arc. Фактически, для владельцев AMD это часто единственный высокопроизводительный вариант, так как ROCm не всегда стабилен. Подробнее в нашей статье "Оптимизация llama.cpp под AMD видеокарты: Vulkan vs ROCm".
А что насчет новых форматов, типа MXFP4?
Новые форматы данных, такие как MXFP4, в первую очередь разрабатываются под аппаратные возможности NVIDIA. Их поддержка в llama.cpp может появиться раньше и быть стабильнее именно в CUDA-бэкенде. Следите за обновлениями в нашем материале про MXFP4.
Стоит ли продавать RTX и покупать AMD?
Однозначно нет. CUDA остается экосистемой с наибольшей поддержкой, стабильностью и количеством оптимизаций для большинства моделей. Vulkan-прирост — это приятный бонус для владельцев NVIDIA и спасательный круг для владельцев AMD. Если вы собираете ферму, то совместимость и доступность драйверов могут быть важнее пиковой скорости на одной карте.
Какой бэкенд выбрать для продакшена?
Правило простое: тестируйте под вашу нагрузку. Запустите бенчмарк на своих промптах, с вашим типичным размером контекста. Если используете llama.cpp server в режиме RPC, убедитесь в стабильности соединения с обоими бэкендами. Наш опыт с распределенными вычислениями показывает, что CUDA пока надежнее в сложных сетапах.
Вывод: следите за развитием экосистемы
Конкуренция между бэкендами в llama.cpp — это благо для пользователей. Vulkan догоняет и в чем-то обгоняет CUDA для конкретных задач, что заставляет разработчиков NVIDIA-ориентированного софта улучшать свои реализации. Наш совет: держите под рукой две сборки llama.cpp (CUDA и Vulkan) и используйте ту, которая дает лучший результат для выбранной модели. Мир локальных LLM быстро меняется, и сегодняшний аутсайдер может стать лидером завтра — как только разработчики оптимизируют код под новый паттерн вычислений.
Ключевой вывод: Не существует «серебряной пули». Производительность LLM-инференса — это всегда компромисс между моделью, квантованием, фреймворком, бэкендом и железом. Vulkan доказал, что может бросить вызов монополии CUDA, и это отличная новость для всей экосистемы.