vLLM кластер на 4 GPU
ТЕХНИЧЕСКОЕ ЗАДАНИЕ: vLLM кластер на 4 GPU
1. Цель задачи
Развернуть vLLM инференс‑сервер на четырёх GPU с включённым tensor parallelism (TP). Провести бенчмарк производительности (throughput, latency) на одном GPU (baseline) и на четырёх GPU с TP=4. Добиться ускорения минимум в 2 раза по throughput при одинаковых условиях (модель, batch size, длина запросов). Научиться конфигурировать multi‑GPU обслуживание больших языковых моделей в production‑стиле.
Ключевой результат vLLM-сервер, запущенный на 4 GPU, выдаёт ≥2× больше запросов в секунду (запросов/сек), чем тот же сервер на одном GPU, при сопоставимой latency (p95 не хуже baseline).
2. Исходные данные
| Что нужно | Откуда взять |
|---|---|
| Сервер с 4 GPU (NVIDIA) | Физическая машина / облачный инстанс (AWS p4d.24xlarge, GCP a2-highgpu-4g, Azure NC96ads) |
| GPU драйверы (≥535), CUDA 12.x | NVIDIA официальный сайт / apt / conda |
| Модель LLM (например, LLaMA-3-70B или Mistral-7B) | Hugging Face, предварительный download |
| Python 3.10+ и PyTorch с CUDA | conda / pip |
| vLLM (≥0.6.0) | pip install vllm |
| Инструменты бенчмарка | vllm.entrypoints.openai.api_server --load-format, lm-eval, собственный скрипт |
| Мониторинг GPU | nvidia-smi, nvtop, gpustat |
Если нет реального сервера с 4 GPU — симулируем:
- Используем облачный инстанс с 4 GPU на 1–4 часа (стоимость ≈ 15–40 $)
- Если облака нет — можно взять машину с 2 GPU и запустить с
--tensor-parallel-size 2, но метрики будут другими. Цель (2×) может быть достигнута и на 2GPU, если модель вмещается - В крайнем случае — Docker контейнер с vllm и
--num-gpus 4на одной физической видеокарте (только для изучения параметров, без реального ускорения)
3. Технологический стек
| Компонент | Инструменты | Назначение |
|---|---|---|
| Язык и среда | Python 3.10+, pip, conda, virtualenv | Запуск vLLM и бенчмарков |
| Инференс‑движок | vLLM (vllm.entrypoints.openai.api_server) | Развёртывание LLM, поддержка TP |
| Frameworks | PyTorch 2.5+, CUDA 12.1+ | Базовые библиотеки для vLLM |
| Доп. утилиты | huggingface_hub, transformers, fastapi, uvicorn | Загрузка модели, API сервер |
| Мониторинг GPU | nvidia-smi, gpustat, nvtop | Загрузка, память, температура |
| Бенчмарк | vllm.entrypoints.openai.run_batch, lm-eval, либо кастомный скрипт (aiohttp, asyncio) | Измерение latency и throughput |
| Документация | Markdown, Jupyter | Анализ результатов, отчёт |
4. Этапы выполнения
Этап 1: Подготовка окружения (2 ч)
Действия
-
Проверить доступные GPU
nvidia-smi nvidia-smi topo -m # topology (важно для TP)Убедиться: ≥4 GPU, драйвер ≥535, CUDA 12.x, связь GPU по NVLink/NVSwitch (если нет – TP будет медленнее).
-
Установить зависимости
conda create -n vllm python=3.10 -y conda activate vllm pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu121 pip install vllm transformers huggingface_hub fastapi uvicorn aiohttp -
Скачать модель
huggingface-cli download meta-llama/Meta-Llama-3-70B --local-dir ./models/Meta-Llama-3-70BЕсли модель не вмещается на один диск – использовать symbolic link или
--cache-dir. -
Проверить, что vLLM стартует на 1 GPU (baseline)
python -m vllm.entrypoints.openai.api_server \ --model ./models/Meta-Llama-3-70B \ --tensor-parallel-size 1 \ --max-model-len 4096 \ --gpu-memory-utilization 0.90 \ --port 8000Убедиться, что сервер отвечает:
curl http://localhost:8000/v1/models
Ожидаемый результат этапа
Этап 2: Бенчмарк baseline (1 GPU) — 3 ч
Действия
-
Написать скрипт для стресс‑теста (или использовать встроенный vllm benchmark)
Пример (bench_baseline.py):import asyncio import aiohttp import time import statistics API_URL = "http://localhost:8000/v1/completions" PROMPTS = ["Explain quantum computing in 3 sentences."] * 100 # 100 одинаковых запросов PAYLOAD = { "model": "./models/Meta-Llama-3-70B", "max_tokens": 128, "temperature": 0 } async def send(session, prompt): payload = {**PAYLOAD, "prompt": prompt} async with session.post(API_URL, json=payload) as resp: return await resp.json() async def main(): async with aiohttp.ClientSession() as session: start = time.monotonic() tasks = [send(session, p) for p in PROMPTS] results = await asyncio.gather(*tasks) total_time = time.monotonic() - start throughput = len(PROMPTS) / total_time latencies = [result["usage"]["total_tokens"] / ...] # можно вычислять токены/сек print(f"Throughput: {throughput:.2f} req/s") # дополнительно: медиана, p95 latency asyncio.run(main()) -
Запустить бенчмарк (не менее 3 прогонов)
python bench_baseline.pyСохранить результаты в baseline_results.json.
-
Измерить baseline метрики
- Throughput (запросов/с)
- Средняя/медианная latency (сек)
- p95 latency
- GPU memory utilisation (nvidia-smi)
- Tokens per second (опционально)
Ожидаемый результат этапа
Файл baseline_results.json с точными задержками и throughput.
Этап 3: Разворот vLLM с Tensor Parallelism на 4 GPU (1 ч)
Действия
-
Остановить сервер baseline (Ctrl+C)
-
Запустить vLLM с TP=4
CUDA_VISIBLE_DEVICES=0,1,2,3 python -m vllm.entrypoints.openai.api_server \ --model ./models/Meta-Llama-3-70B \ --tensor-parallel-size 4 \ --max-model-len 4096 \ --gpu-memory-utilization 0.90 \ --port 8001- Параметр
--tensor-parallel-size 4распределяет слои модели по 4 GPU. - Убедиться, что все 4 GPU загружены (nvidia-smi показывает > 90% памяти).
- Увеличить
--gpu-memory-utilizationдо 0.95 если модель не помещается.
- Параметр
-
Проверить, что сервер отвечает
curl http://localhost:8001/v1/models
Ожидаемый результат этапа
Работающий vLLM сервер на 4 GPU с TP=4, отвечающий на запросы.
Этап 4: Бенчмарк TP=4 и сравнение с baseline (3 ч)
Действия
-
Адаптировать скрипт бенчмарка
-
Запустить 3+ прогона
python bench_tp4.pyСохранить в
tp4_results.json. -
Вычислить ускорение
speedup = throughput_tp4 / throughput_baseline print(f"Speedup: {speedup:.2f}x")Если ускорение <2× → перейти к этапу оптимизации (Этап 5).
-
Собрать latency-распределение (p50, p95, p99) и загрузку GPU для обоих конфигураций.
Ожидаемый результат этапа
Таблица сравнения baseline vs TP4, расчёт ускорения, понимание узких мест.
Этап 5: Оптимизация для достижения ≥2× ускорения (3 ч)
Действия
-
Анализ узких мест
-
Настройки повышения throughput
-
Повторный замер
После каждой оптимизации запускать бенчмарк и сохранять промежуточные результаты.
Цель: throughput ≥ 2× baseline при acceptable latency (p95 не более 2× от baseline). -
Фиксация лучшей конфигурации
Создатьdeploy_tp4.shс оптимальным набором флагов.
Ожидаемый результат этапа
Достигнуто ≥2× ускорение; зафиксирован конфигурационный файл (config_tp4.json) и итоговый бенчмарк final_results.json.
5. Критерии приемки (Definition of Done)
- Сервер vLLM успешно запустился на 4 GPU с
--tensor-parallel-size 4 - Проведён минимум 3 замера baseline (1 GPU) и 3 замера TP=4
- Условия замеров идентичны: одна модель, одинаковые промпты, batch size, длина генерации
- Ускорение по throughput >= 2.0× (отношение запросов/с TP4 к baseline)
- p95 latency при TP4 не превышает 2× p95 baseline (или оговорено иначе)
- Конфигурация итогового запуска документирована (параметры, версии, команды)
- Результаты сохранены в
benchmark_report.mdс таблицами и графиками (matplotlib/plotly) - Результаты воспроизводимы на другой машине (если есть специфика – указана)
6. Ожидаемый результат
Основной артефакт
benchmark_report.md – отчёт, содержащий:
- Описание окружения (GPU, драйвер, версии ПО)
- Команды запуска (baseline и TP4)
- Таблица метрик:
| Конфигурация | Throughput (req/s) | p50 lat (s) | p95 lat (s) | GPU mem (GB avg) |
|---|---|---|---|---|
| 1 GPU | X.X | Y.Y | Z.Z | W.W |
| 4 GPU (TP=4) | X.X | Y.Y | Z.Z | W.W |
- График latency distribution (CDF)
- Вывод: достигнуто / не достигнуто 2× ускорение, если нет – анализ причин
Дополнительно (опционально):
- Скрипты
bench_baseline.py,bench_tp4.py - Файл
deploy_tp4.shс оптимальным запуском - Логи
nvidia-smi dmon(опция)
7. Возможные сложности и их решение
| Сложность | Решение |
|---|---|
| Модель не влезает в 4 GPU | Использовать квантизацию (AWQ/GPTQ) или модель с меньшим числом параметров (например, 13B вместо 70B). Проверить --gpu-memory-utilization 0.95. |
| Ускорение <2× | Убедиться, что GPU соединены NVLink (а не PCIe). Уменьшить batch size или количество потоков. Проверить CPU‑GPU bottleneck. |
| vLLM выдаёт OOM | Уменьшить max-model-len, max-num-seqs, использовать --swap-space. |
| Запросы возвращают ошибки | Проверить формат промптов, версию модели, совместимость с эндпоинтом /v1/completions. |
| latency выше baseline | Возможно, меж‑GPU коммуникация перевешивает выгоду от параллелизма. Попробовать увеличить max-num-seqs до 256–512. |
| Бенчмарк не воспроизводится | Зафиксировать seed, temperature=0, одинаковое количество токенов. Использовать --load-format safetensors. |
8. Бюджет времени (оценка)
| Этап | Описание | Время (ч) |
|---|---|---|
| 1 | Подготовка окружения | 2 |
| 2 | Бенчмарк baseline (1 GPU) | 3 |
| 3 | Разворот TP=4 | 1 |
| 4 | Бенчмарк TP=4 и сравнение | 3 |
| 5 | Оптимизация до ≥2× | 3 |
| Итого | 12 |
Примечание для первого раза может потребоваться +3–4 часа на отладку и понимание vLLM опций.
9. Связанные вопросы из базы знаний
| Вопрос | Тема |
|---|---|
| 112 | vLLM и throughput (влияние batch) |
| 203 | Distributed inference с TP |
| 315 | Бенчмаркинг LLM (метрики, инструменты) |
| 421 | CUDA multi‑GPU программирование |
| 538 | Квантование AWQ для LLM |
| 674 | Docker‑контейнеризация ML‑сервисов |
| 789 | Мониторинг GPU (nvidia‑smi, gpustat) |
| 810 | Масштабирование инференса LLM |
| 891 | Tensor Parallel vs Pipeline Parallel |
10. Чек-лист самопроверки
- Я установил vLLM и проверил, что сервер запускается на одном GPU (curl работает)
- Я замерил baseline не менее 3 раз и записал результаты
- Я запустил vLLM с
--tensor-parallel-size 4и проверил, что все 4 GPU заняты - Я провёл идентичный бенчмарк на 4 GPU и подсчитал ускорение
- Я добился ускорения ≥2× или задокументировал причины, по которым это не удалось
- Я сохранил все конфигурации и результаты в финальный отчёт