Поднимаем LLM с открытыми весами на H100 через vLLM

От чистого образа Ubuntu до OpenAI-совместимого эндпоинта для Llama 3.1 70B в FP8: важные флаги и измеренная нами пропускная способность.

GCGPU-команда CheapServАвтор 9 мин чтения
Видеокарта парит над пьедесталом, от неё расходятся лучи света
На этой странице8
  1. Что поместится на одну H100
  2. Базовая система
  3. Флаги, которые действительно важны
  4. Юнит systemd, который переживает перезагрузки
  5. Обратный прокси с API-ключом
  6. Что мы измерили
  7. Мониторинг
  8. Когда пора идти дальше

Именно такую конфигурацию мы используем в шаблоне vLLM на тарифах с H100. Здесь она расписана по шагам, чтобы вы могли воспроизвести её на чистом образе Ubuntu или адаптировать под себя. Цель — эндпоинт, устроенный как в продакшене: Llama 3.1 70B Instruct в FP8 на одной H100 с 80 GB, OpenAI-совместимый API за обратным прокси с API-ключом и достаточно замеров, чтобы понять, когда пора добавлять вторую карту.

Что поместится на одну H100

Модель на 70B помещается на карту с 80 GB только при условии, что веса квантизованы. В FP8 веса Llama 3.1 70B занимают около 70 GB, и после накладных расходов CUDA и vLLM под KV-кэш остаётся примерно 8 GB. Этого хватает на контекст 32k при нескольких параллельных последовательностях либо на контекст 8k примерно при 40. Если вам нужны длинные контексты и высокая параллельность на 70B, берите две H100 с тензорным параллелизмом; если не нужно ни то ни другое, модель 8B или 14B на RTX 5090 обойдётся в разы дешевле и будет отвечать быстрее.

МодельТочностьВесаОстаётся под KV-кэш (80 GB)Комфортная параллельность при 8k
Llama 3.1 8BBF1616 GB~58 GB200+
Qwen2.5 32BFP833 GB~41 GB~120
Llama 3.1 70BFP870 GB~8 GB~40
Llama 3.1 70BBF16140 GBне помещаетсяминимум 2× H100

Базовая система

Начните с базового образа Ubuntu 24.04 · CUDA 12.8 · driver 570. Проверьте карту и драйвер, затем создайте окружение Python. Мы используем uv, потому что он за секунды подбирает нужные wheel-пакеты с CUDA.

nvidia-smi --query-gpu=name,memory.total,driver_version --format=csv
curl -LsSf https://astral.sh/uv/install.sh | sh
uv venv /opt/vllm && source /opt/vllm/bin/activate
uv pip install vllm==0.6.6 huggingface_hub[cli]

Войдите в Hugging Face, используя токен аккаунта, принявшего лицензию Llama, и заранее скачайте веса на постоянный том, чтобы переустановка не обошлась вам в 70 GB трафика:

huggingface-cli login
huggingface-cli download neuralmagic/Meta-Llama-3.1-70B-Instruct-FP8 --local-dir /data/models/llama-70b-fp8

Флаги, которые действительно важны

У vLLM около сотни флагов. Пять из них определяют, будет ли сервер хорошим.

vllm serve /data/models/llama-70b-fp8 \
  --served-model-name llama-3.1-70b \
  --max-model-len 16384 \
  --gpu-memory-utilization 0.95 \
  --max-num-seqs 48 \
  --enable-prefix-caching \
  --host 127.0.0.1 --port 8000
  • --max-model-len резервирует KV-кэш на каждую последовательность. Задавайте длину самого длинного промпта, который вы реально будете обслуживать, а не максимум модели: при 16k память на один слот вдвое меньше, чем при 32k.
  • --gpu-memory-utilization 0.95 безопасен на карте, на которой больше ничего не запущено. Если вы делите GPU со вторым процессом, оставьте значение по умолчанию — 0.9.
  • --max-num-seqs ограничивает число параллельных последовательностей. Слишком много — запросы выстраиваются в очередь внутри планировщика и дают длинные «хвосты» задержек; слишком мало — карта простаивает. Для 70B FP8 при 16k начните с 48 и дальше подстраивайте значение по метрикам.
  • --enable-prefix-caching переиспользует KV-блоки для одинаковых префиксов промптов, а в чате это почти весь системный промпт. Почти ничего не стоит и нередко даёт от 20 до 30% пропускной способности на чат-трафике.
  • --host 127.0.0.1: у vLLM нет аутентификации. Он ни в коем случае не должен слушать публичный интерфейс.

Юнит systemd, который переживает перезагрузки

cat > /etc/systemd/system/vllm.service <<'EOF'
[Unit]
Description=vLLM OpenAI-compatible server
After=network-online.target
[Service]
User=vllm
Environment=HF_HOME=/data/hf
ExecStart=/opt/vllm/bin/vllm serve /data/models/llama-70b-fp8 --served-model-name llama-3.1-70b --max-model-len 16384 --gpu-memory-utilization 0.95 --max-num-seqs 48 --enable-prefix-caching --host 127.0.0.1 --port 8000
Restart=always
RestartSec=5
[Install]
WantedBy=multi-user.target
EOF
useradd -r -d /data -s /usr/sbin/nologin vllm && chown -R vllm /data
systemctl daemon-reload && systemctl enable --now vllm
journalctl -fu vllm

Загрузка 70 GB весов с NVMe занимает около 90 секунд. Строка в логе Uvicorn running on http://127.0.0.1:8000 означает, что сервер готов.

Обратный прокси с API-ключом

Caddy сам получает сертификат и проверяет bearer-токен тремя строками. Сначала направьте DNS-запись на сервер.

apt install -y caddy
cat > /etc/caddy/Caddyfile <<'EOF'
llm.example.com {
  @noauth not header Authorization "Bearer CHANGE-ME-32-RANDOM-CHARS"
  respond @noauth 401
  reverse_proxy 127.0.0.1:8000 {
    flush_interval -1
  }
}
EOF
systemctl reload caddy

Именно flush_interval -1 заставляет потоковые ответы идти потоком, а не копиться в буфере. Проверьте через OpenAI SDK: задайте base_url равным https://llm.example.com/v1, а api_key — токену; больше в клиенте ничего менять не нужно.

Что мы измерили

С приведёнными выше настройками, на одной H100 SXM, при промпте в 1,000 токенов и ответах по 300 токенов:

Параллельные запросыВыходные токены/с (суммарно)Время до первого токенаТокены/с на запрос
1340.28 s34
82300.41 s29
326400.9 s20
487201.6 s15

Кривая выходит на плато при 40–48 параллельных последовательностях; дальше очередь только добавляет задержку. Если ваш трафик регулярно держится выше этого уровня, следующий шаг — вторая H100 с --tensor-parallel-size 2: она примерно вдвое увеличивает пропускную способность и заодно открывает путь к BF16.

Мониторинг

vLLM отдаёт метрики Prometheus по адресу /metrics. Алерты стоит настроить на три метрики: vllm:num_requests_waiting (значение выше нескольких единиц дольше минуты означает, что сервер насыщен), vllm:gpu_cache_usage_perc (выше 90% означает, что последовательности вытесняются из кэша) и vllm:e2e_request_latency_seconds по p95. Для самой карты добавьте nvidia-smi dmon -s um или дополнение netdata.

Когда пора идти дальше

О том, что установка переросла одну карту, говорят три признака: метрика ожидающих запросов редко равна нулю, вашему продукту нужны контексты 32k при реальной параллельности или вы хотите обслуживать сразу две модели. Все три случая решаются тарифами с 2× и 4× H100, где тот же файл юнита работает с добавленным флагом тензорного параллелизма. А пока эта единственная карта за фиксированную ежемесячную цену обслуживает на удивление много трафика.

GC
GPU-команда CheapServ

Бенчмарки, образы и шаблоны для парка GPU-серверов.

Разверните первый сервер меньше чем за минуту.

Пополните баланс от $25 в BTC, ETH, XMR или USDT. Баланс не сгорает, а неиспользованные средства можно вернуть.

Создать аккаунт