中文翻译暂不可用,显示俄语原文。

Развернуть vLLM против TGI и сравнить throughput

ТЕХНИЧЕСКОЕ ЗАДАНИЕ: Развернуть vLLM против TGI и сравнить throughput

1. Цель задачи

Практически сравнить два популярных inference-сервера для LLM — vLLM и Text Generation Inference (TGI) — на одинаковой модели и одинаковом железе. Измерить throughput (токенов/сек) и latency при идентичной нагрузке. Определить, насколько vLLM быстрее TGI в условиях production-подобного бенчмарка (целевое ускорение 20–50%).

Ключевой результат Два контейнерных развёртывания модели (vLLM и TGI), воспроизводимый бенчмарк-скрипт и сводный отчёт с графиками и численными метриками, подтверждающий/опровергающий гипотезу ускорения.


2. Исходные данные

Перед началом необходимо иметь:

Что нужноОткуда взять
Модель (например, meta-llama/Llama-2-7b-chat-hf)Hugging Face Hub (предварительно получить доступ)
GPU-инстанс (минимум 16 GB VRAM, например, NVIDIA T4, A10G, RTX 4090)Облачный провайдер (AWS, GCP, Lambda Labs) или локальная машина
Docker + NVIDIA Container ToolkitОфициальная документация NVIDIA
Python 3.10+Установленный на хосте
Утилиты для нагрузки (ab, locust или собственный скрипт)Стандартные пакеты / pip

Если нет реального GPU — симулируем:

  1. Заменить модель на меньшую (например, TinyLlama/TinyLlama-1.1B-Chat-v0.6) — влезет в 2 GB VRAM и даст корректный паттерн сравнения.
  2. Использовать CPU-режим (не рекомендуется, т.к. throughput будет несопоставимо низким и не отразит разницу между серверами). Лучше взять маленький GPU-инстанс (T4 от Google Colab — бесплатно, но лимит по времени).
  3. Запускать оба сервера последовательно на одном и том же GPU, фиксировать util GPU через nvidia-smi для честности.

3. Технологический стек

КомпонентИнструментыНазначение
Inference сервер #1vLLM (контейнер vllm/vllm-openai:latest)Serving модели с PagedAttention
Inference сервер #2TGI (контейнер ghcr.io/huggingface/text-generation-inference:latest)Serving модели с continuous batching
МодельHugging Face Llama-2-7b-chat-hfЦелевая LLM
БенчмаркPython (aiohttp + asyncio) + curlГенерация синтетической нагрузки
Мониторингnvidia-smi, docker stats, Prometheus (опционально)Загрузка GPU, память, время
Виртуальная средаDocker Compose (опционально)Оркестрация контейнеров
ОтчётJupyter Notebook / Markdown + PlotlyВизуализация результатов

4. Этапы выполнения

Этап 1: Подготовка окружения и развёртывание vLLM (2–3 часа)

Действия

  1. Установить Docker и NVIDIA Container Toolkit (если не установлено).
    Проверить: sudo docker run --rm --gpus all nvidia/cuda:11.8-base nvidia-smi

  2. Создать директорию проекта и файл .env с переменными:
    MODEL_NAME=meta-llama/Llama-2-7b-chat-hf
    HF_TOKEN=<ваш токен> (только для gated моделей)

  3. Запустить контейнер vLLM с OpenAPI-совместимым эндпоинтом:

    docker run --gpus all \
      -p 8000:8000 \
      -e HF_TOKEN=$HF_TOKEN \
      vllm/vllm-openai:latest \
      --model $MODEL_NAME \
      --max-model-len 4096 \
      --tensor-parallel-size 1 \
      --gpu-memory-utilization 0.90
    

    Примечание: Если GPU мало, уменьшить --max-model-len до 2048.

  4. Проверить, что сервер отвечает:

    curl -X POST http://localhost:8000/v1/completions \
      -H "Content-Type: application/json" \
      -d '{"model": "meta-llama/Llama-2-7b-chat-hf", "prompt": "Hello", "max_tokens": 50}'
    

Ожидаемый результат этапа
Контейнер vLLM запущен, модель загружена, API отвечает на запросы.

Этап 2: Развёртывание TGI (1.5–2 часа)

Действия

  1. Запустить контейнер TGI на порту 8080 (чтобы не конфликтовать):

    docker run --gpus all \
      -p 8080:80 \
      -e HF_TOKEN=$HF_TOKEN \
      ghcr.io/huggingface/text-generation-inference:latest \
      --model-id $MODEL_NAME \
      --max-total-tokens 4096 \
      --max-input-length 1024 \
      --max-batch-prefill-tokens 4096
    
  2. Проверить TGI (эндпоинт /generate):

    curl -X POST http://localhost:8080/generate \
      -H "Content-Type: application/json" \
      -d '{"inputs": "Hello", "parameters": {"max_new_tokens": 50}}'
    
  3. Убедиться, что обе модели работают на одном GPU (не одновременно).
    Для честности перед каждым тестом перезапускать второй контейнер, чтобы освободить VRAM.

Ожидаемый результат этапа
Контейнер TGI работает, API отвечает корректно.

Этап 3: Написание бенчмарк-скрипта (1.5–2 часа)

Действия

  1. Создать Python скрипт benchmark.py с функциями:

  2. Использовать aiohttp для асинхронных запросов:

    async def send_request(session, url, payload):
        async with session.post(url, json=payload) as resp:
            return await resp.json(), resp.status
    
  3. Фиксировать метрики:

    • Latency каждого запроса (time to first token + полное время)
    • Throughput (количество сгенерированных токенов / общее время)
    • Использование GPU (через nvidia-smi --query-gpu=utilization.gpu,memory.used --format=csv -l 1 в параллельном процессе)
  4. Подготовить набор промптов (50–100 штук) фиксированной длины (например, 128 токенов) и запросить генерацию 256 токенов.
    Промпты можно взять из датасета wikitext или сгенерировать случайно.

  5. Запустить скрипт последовательно для vLLM и TGI (с перезапуском контейнера между тестами).

Ожидаемый результат этапа
Скрипт выдаёт CSV-файл с колонками: server, request_id, prompt_len, gen_len, latency_sec, ttft_sec, gpu_util, gpu_mem.

Этап 4: Сбор данных и визуализация (1 час)

Действия

  1. Запустить бенчмарк для vLLM:
    python benchmark.py --server vllm --url http://localhost:8000/v1/completions --model llama-2-7b --output vllm_results.csv
    
  2. Остановить vLLM, запустить TGI, повторить команду с соответствующим URL (http://localhost:8080/generate).
  3. Построить графики в Jupyter Notebook:
    • Boxplot latency (общая)
    • Throughput (токенов/сек) для каждого сервера
    • Зависимость latency от размера батча (если меняли concurrency)
    • GPU utilisation по времени
  4. Вычислить средний throughput и процент ускорения vLLM относительно TGI.

Ожидаемый результат этапа
Ноутбук с графиками и сводной таблицей метрик.

Этап 5: Анализ и оформление отчёта (1–2 часа)

Действия

  1. Сформулировать вывод:

    • Достигнуто ли целевое ускорение 20–50%?
    • Какие конфигурации влияют на разницу (batch size, max_tokens, GPU memory)?
    • Сравнить TTFT (time to first token) и throughput при разной нагрузке.
  2. Написать отчёт в формате README.md с секциями:

    • Методология (модель, железо, параметры)
    • Результаты (таблицы + графики)
    • Выводы и рекомендации
  3. Сохранить все артефакты в репозиторий Git.

Ожидаемый результат этапа
Готовый отчёт в репозитории с чётким вердиктом.


5. Критерии приемки (Definition of Done)

  • vLLM и TGI развёрнуты в Docker-контейнерах на одном GPU.
  • Бенчмарк-скрипт воспроизводим и параметризован (модель, url, concurrency, промпты).
  • Собраны метрики для минимум 50 запросов на каждый сервер при одинаковых условиях.
  • Построены графики latency и throughput.
  • Вычислено процентное ускорение vLLM относительно TGI (или наоборот).
  • Проведён анализ влияния размера батча (concurrency) на разницу.
  • Написана секция «Выводы» с объяснением причин ускорения/замедления.
  • Отчёт содержит раздел «Возможные источники погрешностей» (например, разная реализация batching, разница в квантовании, влияние контейнеров).
  • Код бенчмарка и отчёт загружены в Git-репозиторий.

6. Ожидаемый результат

Основной артефакт
Репозиторий со следующей структурой:

benchmark_llm/
├── docker_compose/          # опциональные docker-compose файлы
├── benchmark.py             # скрипт нагрузочного тестирования
├── prompts.json             # тестовые промпты
├── vllm_results.csv
├── tgi_results.csv
├── analysis.ipynb           # ноутбук с графиками
├── report.md                # итоговый отчёт
└── README.md                # инструкция по запуску

Содержание отчёта

  • Таблица сравнения: средний throughput (токенов/сек), p50/p95 latency, TTFT.
  • Графики: CDF latency, scatter plot latency vs. batch.
  • Вывод: подтверждено ли ускорение vLLM на 20–50%? Если нет – объяснение.

Дополнительные результаты

  • Разобран механизм continuous batching в vLLM и TGI.
  • Понимание того, как параметры --gpu-memory-utilization и --max-batch-prefill-tokens влияют на производительность.

7. Возможные сложности и их решение

СложностьРешение
Модель не влезает в VRAM (Out of Memory)Использовать --quantization awq или bitsandbytes 4-bit; уменьшить --max-model-len до 2048; взять меньшую модель (7B → 1.1B)
Ошибка CUDA out of memory при параллельном запускеЗапускать серверы строго последовательно, между тестами перезапускать Docker и чистить кэш (docker system prune -a для верности)
Разные версии API: vLLM использует /v1/completions, TGI – /generateУнифицировать вызовы в бенчмарк-скрипте через условный URL и формат payload
Разница в параметрах по умолчанию (например, max_new_tokens vs max_tokens)Явно указывать max_tokens и temperature=0 (greedy decoding) для воспроизводимости
Нестабильные замеры из-за фоновых процессовОтключить оболочки (GUI), фиксировать utilisation GPU, повторить тест 3 раза
Проблемы с аутентификацией Hugging FaceИспользовать --env HF_TOKEN при запуске контейнера; скачать модель заранее через huggingface-cli login

8. Бюджет времени (оценка)

ЭтапДлительность
1. Подготовка и развёртывание vLLM2–3 ч
2. Развёртывание TGI1.5–2 ч
3. Написание бенчмарк-скрипта1.5–2 ч
4. Сбор данных и визуализация1–1.5 ч
5. Анализ и оформление отчёта1–2 ч
Итого7–10.5 ч

Примечание Для первого выполнения рекомендую заложить 1 день + запас на отладку (особенно если железо слабое). Повторный прогон займёт не более 2–3 часов.


9. Связанные вопросы из базы знаний

ВопросТема
10Как работает PagedAttention в vLLM?
42Сравнение continuous batching vLLM и TGI
67Настройка tensor parallelism для одной GPU
134Влияние max-batch-prefill-tokens на throughput
203Метрики: throughput, latency, TTFT – определения
210Почему vLLM быстрее при одинаковом hardware?
311Оптимизация GPU memory utilisation для inference
405Асинхронное нагрузочное тестирование с aiohttp
512Оценка производительности LLM сервера через Prometheus
689Квантование моделей (AWQ, GPTQ) и его влияние на throughput

10. Чек-лист самопроверки

  • Я развернул vLLM и TGI с одинаковыми параметрами (модель, max_tokens, dtype).
  • Перед каждым тестом я убедился, что второй сервер остановлен, чтобы не делить GPU.
  • Я использую одинаковый набор промптов и одинаковое количество запросов для обоих серверов.
  • Я измерил throughput как (сумма всех сгенерированных токенов) / (общее время теста).
  • Я проверил, что ответы содержат usage с количеством токенов, или посчитал их через tokenizer.
  • Я построил хотя бы один график (CDF latency, throughput vs concurrency).
  • Я сформулировал конкретные цифры ускорения/замедления и обосновал их технически.
  • Я описал, какие погрешности могли повлиять на результат (температура, фоновые процессы, версии CUDA).
  • Я сохранил исходные CSV-файлы и код бенчмарка в Git.