Як запустити кілька LLM моделей на одному GPU — практичний гайд для розробників

Практичний посібник для розробників про запуск кількох LLM моделей одночасно на одному GPU

Якщо у вас є один GPU і ви хочете одночасно крутити кілька мовних моделей — наприклад, Mistral для чату і LLaMA для summarization — без покупки додаткового заліза, цей туторіал саме для вас. Ми розглянемо підхід через vLLM з мультиадаптерним режимом і Ollama з паралельними процесами, що дозволяє ефективно ділити VRAM між моделями. Весь процес займе приблизно 45–60 хвилин, якщо у вас вже налаштоване середовище з CUDA. На старті вам потрібен Linux-сервер або WSL2, GPU від 16 GB VRAM (наприклад, RTX 4090 або A100), і базові знання термінала.

🛠️ Що знадобиться

  • NVIDIA GPU (16+ GB VRAM) — основний ресурс, який ми будемо ділити між моделями; підійде RTX 4090, A100, або L4 у хмарі
  • vLLM 0.6+ — фреймворк для ефективного inference з підтримкою PagedAttention і мультиадаптерів; безкоштовний, open-source
  • Ollama 0.5+ — простий менеджер моделей з REST API; безкоштовний, ідеально для локального dev-середовища
  • Docker та NVIDIA Container Toolkit — для ізоляції сервісів і доступу до GPU з контейнерів; безкоштовний
  • Python 3.11+ — для скриптів управління та тестування; безкоштовний
  • tmux або supervisor — для запуску кількох процесів одночасно у фоні; безкоштовний

📋 Покрокова інструкція

Крок 1: Перевірка GPU та встановлення залежностей

Спочатку переконайтесь, що CUDA і драйвери встановлені коректно. Відкрийте термінал і виконайте nvidia-smi — ви маєте побачити таблицю з назвою GPU, версією драйвера і доступним VRAM. Якщо команда не знайдена, встановіть драйвери командою sudo apt install nvidia-driver-565 nvidia-cuda-toolkit і перезавантажте систему. Далі встановіть NVIDIA Container Toolkit: виконайте curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey | sudo gpg --dearmor -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg, потім sudo apt-get install -y nvidia-container-toolkit і sudo nvidia-ctk runtime configure --runtime=docker. Після цього sudo systemctl restart docker — Docker тепер бачить ваш GPU.

Крок 2: Встановлення vLLM і підготовка першої моделі

Встановіть vLLM у віртуальне середовище: виконайте python3 -m venv vllm-env, потім source vllm-env/bin/activate і pip install vllm==0.6.3. Тепер запустіть першу модель — Mistral 7B — вказавши обмеження на GPU пам’ять у 45% через параметр --gpu-memory-utilization: виконайте команду python -m vllm.entrypoints.openai.api_server --model mistralai/Mistral-7B-Instruct-v0.3 --gpu-memory-utilization 0.45 --port 8001 --served-model-name mistral. Це ключовий момент: параметр 0.45 означає, що vLLM зарезервує лише 45% VRAM, залишаючи простір для другої моделі. Перший запуск завантажить модель з Hugging Face — це може зайняти 5–10 хвилин залежно від швидкості інтернету. Сервер готовий, коли у логах з’явиться рядок Uvicorn running on http://0.0.0.0:8001.

Крок 3: Запуск другої моделі в окремому терміналі через tmux

Відкрийте новий tmux-сесію командою tmux new-session -d -s model2, потім підключіться до неї: tmux attach -t model2. Активуйте те саме середовище: source vllm-env/bin/activate. Тепер запустіть другу модель — Qwen2.5 7B — але вже на порту 8002 і з тими ж 45% VRAM: python -m vllm.entrypoints.openai.api_server --model Qwen/Qwen2.5-7B-Instruct --gpu-memory-utilization 0.45 --port 8002 --served-model-name qwen. Підводний камінь: якщо сума утилізації перевищить 90–95% фізичного VRAM, друга модель впаде з помилкою CUDA out of memory. Щоб цього уникнути — виконайте nvidia-smi після запуску першої моделі і перевірте реальне споживання перед стартом другої. На RTX 4090 (24 GB) два Mistral/Qwen 7B у 4-bit квантизації займають приблизно по 5–6 GB кожен.

Крок 4: Налаштування Nginx як єдиного API-шлюзу

Щоб не відкривати два порти клієнтам, налаштуємо Nginx-проксі, який буде маршрутизувати запити за назвою моделі. Встановіть Nginx: sudo apt install nginx. Відкрийте файл конфігурації: sudo nano /etc/nginx/sites-available/llm-gateway і вставте наступне: створіть два upstream блоки — upstream mistral_backend { server 127.0.0.1:8001; } і upstream qwen_backend { server 127.0.0.1:8002; }. У блоці server на порту 80 додайте location /v1/mistral/ { proxy_pass http://mistral_backend/v1/; } і location /v1/qwen/ { proxy_pass http://qwen_backend/v1/; }. Збережіть файл, виконайте sudo ln -s /etc/nginx/sites-available/llm-gateway /etc/nginx/sites-enabled/ і sudo nginx -t для перевірки синтаксису, потім sudo systemctl reload nginx. Тепер запити до http://localhost/v1/mistral/chat/completions ідуть до першої моделі, а до /v1/qwen/ — до другої.

Крок 5: Тестування і моніторинг навантаження

Перевірте роботу обох моделей одночасно — відкрийте два термінали і запустіть паралельні запити. У першому виконайте: curl http://localhost/v1/mistral/chat/completions -H "Content-Type: application/json" -d '{"model":"mistral","messages":[{"role":"user","content":"Привіт! Хто ти?"}]}'. У другому: curl http://localhost/v1/qwen/chat/completions -H "Content-Type: application/json" -d '{"model":"qwen","messages":[{"role":"user","content":"Solve 2+2"}]}'. Обидва мають відповісти протягом 2–5 секунд. Для моніторингу VRAM у реальному часі запустіть watch -n 1 nvidia-smi в окремому вікні — ви побачите, як пам’ять розподілена між двома процесами Python. Кінцевий результат: два незалежні LLM-сервіси на одному GPU, доступні через єдиний API-шлюз з маршрутизацією за endpoint.

⚠️ Типові помилки та як їх уникнути

  • CUDA Out of Memory при старті другої моделі — зменшіть --gpu-memory-utilization до 0.40 для кожної моделі або використовуйте 4-bit квантизацію, додавши прапор --quantization awq до команди запуску vLLM
  • Конфлікт портів між процесами — перед запуском виконайте lsof -i :8001 і lsof -i :8002; якщо порт зайнятий — завершіть процес командою kill -9 [PID] або змініть порт у параметрі --port
  • Модель завантажується, але відповідає надто повільно — швидше за все, активований CPU offload через брак VRAM; перевірте nvidia-smi і переконайтеся, що GPU utilization під час inference сягає 90%+, а не 10–20%
  • vLLM падає з помилкою про версію CUDA — vLLM 0.6+ вимагає CUDA 12.1 або вище; перевірте командою nvcc --version і оновіть toolkit через sudo apt install cuda-toolkit-12-4

💡 Поради для кращого результату

Використовуйте AWQ або GPTQ квантизацію: замість стандартних float16 моделей завантажуйте версії з HuggingFace у форматі AWQ — вони займають удвічі менше VRAM при мінімальній втраті якості. Додайте --quantization awq до команди vLLM і завантажте модель типу TheBloke/Mistral-7B-Instruct-v0.2-AWQ. Налаштуйте різні розміри KV-cache: якщо одна модель використовується рідко, обмежте її кеш через --max-model-len 4096 замість дефолтних 32768 — це звільнить сотні мегабайт VRAM. Моніторте через Prometheus + Grafana: vLLM нативно експортує метрики на /metrics — підключіть їх до Grafana і відстежуйте latency та throughput кожної моделі окремо в реальному часі. Для dev-середовища спробуйте Ollama з паралельними запитами: з версії 0.5 Ollama підтримує OLLAMA_MAX_LOADED_MODELS=2 як змінну середовища — це найшвидший спосіб підняти дві моделі за 5 хвилин без додаткового конфігурування.

❓ Часті запитання (FAQ)

1. Чи можна запустити три і більше моделей на одному GPU?
Технічно так, але практично обмежує VRAM. На 24 GB GPU реально тримати три моделі по 7B у 4-bit квантизації (кожна ~4 GB). Головне — щоб сума --gpu-memory-utilization не перевищувала 0.90 і залишався буфер для KV-cache під час inference.

2. Чи сповільнюються моделі, коли працюють одночасно?
Так, є деградація throughput, але не критична. Якщо моделі отримують запити одночасно, вони конкурують за GPU cores — загальна пропускна здатність ділиться. Якщо ж запити чергуються, кожна модель отримує повний ресурс GPU у свій момент.

3. Як це працює з моделями різного розміру, наприклад 7B і 70B?
Модель 70B у float16 потребує ~140 GB VRAM, що не вміщається навіть на A100 80 GB разом з іншою моделлю. Рішення — tensor parallelism через --tensor-parallel-size або квантизація до 4-bit (тоді 70B займає ~35 GB), що вже дозволяє сумісне розміщення з малою моделлю на A100.

4. Чи підходить цей підхід для продакшн-навантаження?
Для помірного трафіку — так. Для high-load рекомендується виділяти окремий GPU на кожну модель або використовувати Kubernetes з NVIDIA MIG (Multi-Instance GPU) на A100/H100, що апаратно ізолює GPU на незалежні секції.

5. Як автоматично перезапускати моделі після перезавантаження сервера?
Замініть tmux на systemd-сервіси. Створіть файл /etc/systemd/system/vllm-mistral.service з секцією [Service], де вкажіть ExecStart з командою запуску і Restart=always. Виконайте sudo systemctl enable vllm-mistral — після цього модель стартуватиме автоматично разом із системою.

🏁 Підсумок

Ви навчились розгортати кілька LLM-моделей на одному GPU через vLLM з контрольованим розподілом VRAM, налаштовувати Nginx як єдиний API-шлюз і моніторити споживання ресурсів у реальному часі. Результат — повноцінний локальний мультимодельний inference-сервер, який коштує нуль доларів на підписки і дає повний контроль над даними.

Починайте прямо зараз з найпростішого: встановіть Ollama командою curl -fsSL https://ollama.com/install.sh | sh, виставте export OLLAMA_MAX_LOADED_MODELS=2 і запустіть ollama run mistral в одному терміналі та ollama run qwen2.5 в іншому — за 10 хвилин матимете робочий прототип без жодного конфігурування.

РОЗСИЛКА

📬 Щотижневий AI-дайджест

Найкращі статті про ШІ та автоматизацію — без спаму, лише суть

Без спаму · Відписатись будь-коли

Telegram