Именно такую конфигурацию мы используем в шаблоне 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 8B | BF16 | 16 GB | ~58 GB | 200+ |
| Qwen2.5 32B | FP8 | 33 GB | ~41 GB | ~120 |
| Llama 3.1 70B | FP8 | 70 GB | ~8 GB | ~40 |
| Llama 3.1 70B | BF16 | 140 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 токенов:
| Параллельные запросы | Выходные токены/с (суммарно) | Время до первого токена | Токены/с на запрос |
|---|---|---|---|
| 1 | 34 | 0.28 s | 34 |
| 8 | 230 | 0.41 s | 29 |
| 32 | 640 | 0.9 s | 20 |
| 48 | 720 | 1.6 s | 15 |
Кривая выходит на плато при 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, где тот же файл юнита работает с добавленным флагом тензорного параллелизма. А пока эта единственная карта за фиксированную ежемесячную цену обслуживает на удивление много трафика.
