Очередь за GPU: когда одна карта должна работать на всех
Представьте лабораторию из пяти исследователей. У вас есть один сервер с RTX 6000 Ada на 48 ГБ VRAM. И пять человек, которым нужно запускать свои модели. Классический сценарий: первый занял карту на три дня для обучения 70B модели, остальные ждут. Или хуже - все пытаются запустить свои процессы одновременно, система падает, а GPU утилизация составляет жалкие 15%.
Знакомо? Я сталкивался с этим десятки раз. В моей предыдущей статье про сборку ПК для локальных LLM я показывал, как собрать систему с несколькими картами. Но что делать, когда физически есть только одна мощная GPU, а пользователей много?
Самый частый косяк: администраторы просто дают всем доступ по SSH и говорят "разбирайтесь сами". Результат - гонка за ресурсами, конфликты CUDA, и в итоге все процессы убиваются OOM killer. Так делать нельзя.
Зачем делить одну карту вместо покупки нескольких?
Сначала разберемся с экономикой. Одна NVIDIA RTX 6000 Ada стоит около 7000$. Четыре RTX 4090 с суммарно похожей производительностью - 6000$. Кажется, выгоднее купить несколько дешевых карт? Не совсем.
Во-первых, серверное оборудование. Для четырех RTX 4090 нужна материнская плата с четырьмя слотами PCIe x16, мощный блок питания 1600W+, система охлаждения. Это минимум 2000-3000$ дополнительно. Во-вторых, энергопотребление и тепло. В-третьих, как я писал в статье про NVLink для RTX 3090, связь между картами - отдельная головная боль.
Три подхода к разделению: от простого к сложному
Все решения делятся на три категории по степени изоляции и сложности настройки:
| Метод | Изоляция | Сложность | Лучший сценарий |
|---|---|---|---|
| CUDA MPS (Multi-Process Service) | Слабая | Низкая | Несколько легких инференс-задач |
| MIG (Multi-Instance GPU) | Сильная | Средняя | Предсказуемые рабочие нагрузки |
| vGPU (Virtual GPU) | Полная | Высокая | Виртуальные машины с GPU |
CUDA MPS: быстро, грязно, и иногда работает
Самый простой способ. CUDA Multi-Process Service позволяет нескольким процессам использовать одну GPU одновременно, минимизируя overhead контекстных переключений. Но изоляции нет - один процесс может съесть всю память и убить остальные.
1 Установка и запуск MPS сервера
Сначала проверяем, поддерживает ли ваша карта MPS:
nvidia-smi -q | grep "MPS"
Если видите "Supported: Yes", продолжаем. Запускаем MPS сервер от root:
# Останавливаем все CUDA процессы
sudo nvidia-smi -pm 0
# Экспортируем переменные для MPS
export CUDA_VISIBLE_DEVICES=0
export CUDA_MPS_PIPE_DIRECTORY=/tmp/nvidia-mps
export CUDA_MPS_LOG_DIRECTORY=/tmp/nvidia-log
# Создаем директории
sudo mkdir -p /tmp/nvidia-mps
sudo mkdir -p /tmp/nvidia-log
# Запускаем control daemon
sudo nvidia-cuda-mps-control -d
2 Запуск процессов через MPS
Теперь пользователи могут запускать свои процессы. Каждый должен установить те же переменные окружения:
export CUDA_VISIBLE_DEVICES=0
export CUDA_MPS_PIPE_DIRECTORY=/tmp/nvidia-mps
export CUDA_MPS_LOG_DIRECTORY=/tmp/nvidia-log
# Запуск llama.cpp с MPS
./main -m models/llama-2-7b.Q4_K_M.gguf -n 512 --gpu-layers 20
Главная проблема MPS: нет контроля за памятью. Пользователь А запускает модель на 40 ГБ, пользователь Б пытается запустить свою - получает CUDA out of memory. Решение? Только мониторинг и правила использования.
MIG: когда нужна настоящая изоляция
Multi-Instance GPU - технология NVIDIA для физического разделения карты на независимые экземпляры. Каждый MIG instance получает выделенные вычислительные ядра, память и bandwidth. Это как разделить физический сервер на виртуальные машины, только для GPU.
Но есть нюансы (их всегда больше, чем в документации):
- Поддерживается только на картах серии A100, A30, H100 и некоторых других серверных
- RTX и GeForce - нет, забудьте
- После включения MIG перезагрузка системы обязательна
- Конфигурация фиксирована - нельзя динамически менять размер instance
3 Настройка MIG на A100
Допустим, у нас A100 80GB. Мы хотим разделить ее на 4 экземпляра по 20GB каждый:
# Включаем режим MIG
sudo nvidia-smi -mig 1
# Перезагружаемся (да, обязательно)
sudo reboot
# После перезагрузки смотрим доступные конфигурации
sudo nvidia-smi mig -lgip
# Видим что-то вроде:
# GPU 0: A100 80GB PCIe (UUID: GPU-xxx)
# MIG 2g.10gb Device: 0">
Выбираем конфигурацию. Для 4 экземпляров по 20GB на A100 подойдет профиль 4g.20gb:
# Создаем 4 экземпляра
sudo nvidia-smi mig -cgi 4g.20gb -C
# Проверяем создание
sudo nvidia-smi -L
# Должны увидеть:
# GPU 0: A100 80GB PCIe (UUID: GPU-xxx)
# MIG 4g.20gb Device 0: (UUID: MIG-xxx)
# MIG 4g.20gb Device 1: (UUID: MIG-xxx)
# MIG 4g.20gb Device 2: (UUID: MIG-xxx)
# MIG 4g.20gb Device 3: (UUID: MIG-xxx)
4 Назначение MIG инстансов пользователям
Теперь нужно назначить каждый инстанс конкретному пользователю. Используем cgroups для изоляции:
# Устанавливаем nvidia-container-toolkit
sudo apt-get install -y nvidia-container-toolkit
# Создаем cgroup для пользователя alice
sudo cgcreate -g devices:alice_gpu
# Назначаем MIG устройство 0 пользователю alice
echo 'c 195:0 rw' | sudo tee /sys/fs/cgroup/devices/alice_gpu/devices.allow
# Запускаем процесс от имени alice в cgroup
sudo cgexec -g devices:alice_gpu sudo -u alice python inference.py
Звучит сложно? Есть способ проще - использовать Docker с поддержкой MIG:
# Запускаем контейнер с конкретным MIG устройством
docker run --gpus '"device=0:0"' \
-it nvcr.io/nvidia/pytorch:23.10-py3 \
python -c "import torch; print(torch.cuda.get_device_name(0))"
vGPU: полная виртуализация для самых требовательных
Virtual GPU - решение для создания виртуальных машин с выделенными GPU ресурсами. vGPU делит физическую карту на несколько виртуальных, каждая из которых видна в гостевой ОС как отдельная GPU.
Плюсы очевидны: полная изоляция, возможность live миграции VM, поддержка разных ОС. Минусы еще очевиднее: нужны лицензии NVIDIA vGPU, специальный гипервизор (VMware, Hyper-V, Xen), и это дорого.
| Решение | Лицензия | Минимальный профиль | Подходит для |
|---|---|---|---|
| NVIDIA vComputeServer | Требуется | 1GB vGPU | Продакшен, предприятия |
| NVIDIA AI Enterprise | Требуется | 4GB vGPU | AI/ML workloads |
| Open-source альтернативы | Бесплатно | Зависит от решения | Лаборатории, R&D |
Slurm: планировщик для дисциплинированных
Если vGPU и MIG - это техническое разделение, то Slurm - организационное. Вы не делите карту физически, а ставите задачи в очередь. Пользователь отправляет задание, Slurm выделяет ему GPU на определенное время.
Это идеально для исследовательских групп. Пользователь А может занять всю карту на 8 часов для обучения модели, пользователь Б - на 30 минут для инференса. Все по расписанию, без конфликтов.
5 Базовая настройка Slurm для одной GPU
Установка Slurm на Ubuntu/Debian:
# Устанавливаем Slurm
sudo apt-get update
sudo apt-get install -y slurm-wlm slurm-wlm-basic-plugins
# Конфигурационный файл /etc/slurm/slurm.conf
# Минимальная конфигурация для одной ноды с GPU:
ControlMachine=your-server-name
SlurmctldPort=6817
SlurmdPort=6818
AuthType=auth/munge
StateSaveLocation=/var/spool/slurm/ctld
SlurmdSpoolDir=/var/spool/slurm/d
SwitchType=switch/none
MpiDefault=none
SlurmctldPidFile=/var/run/slurmctld.pid
SlurmdPidFile=/var/run/slurmd.pid
ProctrackType=proctrack/cgroup
ReturnToService=2
SlurmctldTimeout=300
SlurmdTimeout=300
# Определяем ноду
NodeName=server CPUs=16 RealMemory=64000 Sockets=1 CoresPerSocket=16 \
ThreadsPerCore=2 State=UNKNOWN
# Определяем партицию (очередь)
PartitionName=normal Nodes=server Default=YES MaxTime=24:00:00 \
State=UP DefMemPerCPU=4000 MaxMemPerCPU=64000
# GPU ресурсы - ключевой момент
GresTypes=gpu
NodeName=server Gres=gpu:rtx6000:1
# Запускаем демоны
sudo systemctl start slurmctld
sudo systemctl start slurmd
6 Отправка заданий с GPU
Пользователь создает скрипт задания:
#!/bin/bash
#SBATCH --job-name=llm-inference
#SBATCH --partition=normal
#SBATCH --gres=gpu:1 # Запрашиваем одну GPU
#SBATCH --time=02:00:00 # Максимум 2 часа
#SBATCH --mem=16G # RAM
#SBATCH --output=slurm-%j.out
# Загружаем окружение
module load cuda/12.1
# Запускаем нашу задачу
python inference.py --model llama-2-70b --gpu-id 0
И отправляет его в очередь:
sbatch inference-job.sh
# Проверяем статус
squeue -u $USER
# Видим что-то вроде:
# JOBID PARTITION NAME USER ST TIME NODES NODELIST(REASON)
# 12345 normal llm-inf alice R 0:05 1 server
Slurm не разделяет GPU технически, а управляет доступом. Это как диспетчер такси - он не режет машину на части, а дает ее разным людям в разное время.
Open OnDemand: веб-интерфейс для тех, кто ненавидит терминал
Не все пользователи хотят или умеют работать с Slurm через командную строку. Open OnDemand дает веб-интерфейс для отправки заданий, доступа к Jupyter Notebooks, и мониторинга ресурсов.
Установка (на базе предыдущей настройки Slurm):
# Устанавливаем зависимости
sudo apt-get install -y apache2 passenger ruby-dev nodejs
# Устанавливаем Open OnDemand
wget https://github.com/OSC/Open-OnDemand/releases/download/v3.0.6/ondemand-release_3.0.6-1_all.deb
sudo dpkg -i ondemand-release_3.0.6-1_all.deb
sudo apt-get update
sudo apt-get install -y ondemand
# Настраиваем аутентификацию (например, через LDAP или PAM)
sudo vim /etc/ood/config/ood_portal.yml
# Перезапускаем
sudo /opt/ood/ood-portal-generator/sbin/update_ood_portal
sudo systemctl restart apache2
Теперь пользователи заходят на https://ваш-сервер, видят доступные GPU, могут запускать Jupyter с автоматическим выделением ресурсов через Slurm.
Гибридный подход: что использовать в 2024
После десятков настроек в разных организациях, я выработал практические рекомендации:
- Для лаборатории из 3-5 исследователей: Slurm + Open OnDemand. Дешево, гибко, не требует лицензий. Пользователи учатся дисциплине.
- Для продакшена с гарантиями SLA: vGPU с NVIDIA AI Enterprise. Дорого, но полная изоляция и live миграция.
- Для предсказуемых рабочих нагрузок: MIG на A100/H100. Каждый получает гарантированные ресурсы.
- Для быстрого прототипирования: CUDA MPS с мониторингом. Быстро настроить, но нужен ответственный администратор.
Мониторинг и диагностика: чтобы знать, кто что творит
Какой бы метод вы не выбрали, без мониторинга будет хаос. Три обязательных инструмента:
1. DCGM Exporter + Grafana
# Устанавливаем DCGM Exporter
docker run -d --gpus all --rm -p 9400:9400 \
nvcr.io/nvidia/k8s/dcgm-exporter:3.3.0-3.1.2-ubuntu20.04
Настраиваем Grafana dashboard для отслеживания: утилизация GPU, память, температура, пользовательские процессы.
2. Prometheus + Alertmanager
Настройка алертов на аномалии:
# prometheus.yml
rule_files:
- "alerts.yml"
alerting:
alertmanagers:
- static_configs:
- targets: ['localhost:9093']
# alerts.yml
groups:
- name: gpu_alerts
rules:
- alert: GPUMemoryHigh
expr: nvidia_gpu_memory_used_bytes / nvidia_gpu_memory_total_bytes > 0.9
for: 5m
labels:
severity: warning
annotations:
summary: "GPU memory usage high on {{ $labels.gpu }}"
description: "GPU {{ $labels.gpu }} memory usage is {{ $value }}%"
3. Пользовательские квоты
Для Slurm настраиваем fairshare политику, чтобы один пользователь не монополизировал ресурсы:
# /etc/slurm/slurm.conf
PriorityType=priority/multifactor
PriorityWeightFairshare=100000
PriorityWeightAge=1000
PriorityWeightPartition=10000
PriorityWeightQOS=0
PriorityMaxAge=7-0
Чего ждать в будущем? NVIDIA не стоит на месте
NVIDIA постепенно улучшает технологии разделения. В Blackwell архитектуре обещают более гибкий MIG с динамическим перераспределением ресурсов. Но пока что - это дорогие серверные карты.
Для потребительского сегмента альтернатива - ROCm от AMD с технологией MxGPU. Но поддержка в AI стеке пока слабее, чем у CUDA.
Мой прогноз: через 2-3 года технологии разделения GPU станут стандартом даже для небольших лабораторий. Как виртуализация CPU стала нормой в 2010-х, так и виртуализация GPU станет нормой в 2020-х.
А пока - выбирайте подход под ваши задачи и бюджет. И помните: идеального решения нет, есть компромиссы. Иногда проще купить вторую карту, чем настраивать сложную систему разделения. Но если бюджет ограничен - теперь вы знаете, как выжать максимум из одного железа.
Самый частый вопрос: "А можно ли разделить RTX 4090 через MIG?" Нет. MIG работает только на серверных картах серии A и H. Для GeForce/RTX используйте Slurm или vGPU с лицензией (что часто дороже самой карты).
Если вам нужно масштабироваться дальше одной карты, посмотрите мою статью про стратегии масштабирования локальных LLM. Там я рассказываю, как перейти от одной разделенной карты к полноценному кластеру.