Фантомная загрузка: почему 95% GPU не значат 95% скорости
Сценарий, от которого у любого SRE дёргается глаз: nvidia-smi показывает 95-98% утилизации GPU, а latency ответов модели растёт в два раза. Команда тычет пальцем в чипы, подозревает thermal throttling, перезагружает драйверы — без толку. А реальность проста до зубного скрежета: виновата подсистема хранения. Не GPU простаивает, а GPU занят бесполезной работой — перекладыванием данных из регистров в память и обратно, пока storage не подвезёт новую порцию весов.
Здесь классический эффект «обмана утилизацией». Современные GPU (Blackwell B200, Maia 200 от Microsoft) умеют переключать контекст так быстро, что планировщик боевого cloud-инференса заполняет все SM «шумом» — командами, которые не требуют свежих данных. GPU формально занят, но не выдаёт результат. Это как если бы таксист крутил руль на месте, а колёса застряли в грязи. Счётчик тикает, вы платите, а машина не едет.
Проблема особенно остра для больших языковых моделей. Llama 3 405B в 4-битном квантовании весит ~140 ГБ. Каждый токен требует последовательного чтения десятков гигабайт весов из RAM или NVMe. Если storage даёт задержку даже на 10% выше нормы — latency первого токена (TTFT) взлетает, throughput падает, а вы продолжаете платить за «занятые» GPU.
Кто на самом деле тормозит: эпитафия RAID-массиву
Три сценария, где подсистема хранения превращает AI-кластер в дыру для денег.
1 Деградировавший RAID (rebuild latency)
RAID5/6 с одним сбойным диском — классика. Массив перестраивается, каждое чтение честного куска данных превращается в вычисление XOR из оставшихся дисков. Латенси чтения растёт с 200 µs до 2-5 ms. Для последовательного чтения модели это катастрофа. GPU, которая должна глотать данные потоком, получает их каплями. В итоге GPU простаивает ровно в той пропорции, в какой storage не успевает. Но утилизация может оставаться высокой из-за спекулятивных вычислений (prefetch, warp scheduling).
Ещё хуже, если кластер использует общую NAS-полку (NFS/GFS2) для хранения чекпоинтов и весов. При деградации одного звена страдают все узлы. Инференс начинает дёргаться — то быстро, то медленно. Именно это, кстати, одна из причин, почему многие переходят на dedicated GPU-ноды с локальным NVMe, как в Google Cloud C4, где storage изолирован.
2 Недостаточный storage throughput для GPU
Современный GPU может потреблять до 3-4 ГБ/с данных при инференсе (зависит от модели и квантования). Если storage выдаёт 1 ГБ/с — вы в два раза теряете в скорости. При этом GPU готов считать быстрее, но данные не поспевают. Мониторинг показывает высокую утилизацию, потому что GPU тратит циклы на ожидание данных в режиме busy-wait? Нет, современные GPU уходят в sleep state при нехватке данных, но операционка всё равно рапортует загрузку как 100% (wall-clock occupancy). Стандартная метрика sm_occupancy выше 90%, а dram_utilization — 30%. Красный флаг: вычислительные блоки перегружены, а память не используется — значит, bottleneck не внутри GPU.
dram_utilization) и per-process I/O статистика — вот что реально показывает проблему.3 Деградированные узлы (silent data corruption)
Память NAND деградирует незаметно. ECC исправляет ошибки, но за счёт повторных чтений. Падение скорости чтения на 15-20% — и вы платите за GPU, который работает вполсилы. Проблема в том, что стандартные health-check на уровне RAID контроллера не показывают увеличение latency на чтение, если нет битых секторов. Только мониторинг percentiles latency (p99 > 1ms) выявляет такие «капризные» диски.
Это особенно актуально для on-premise кластеров. В облачных решениях, например, новых инстансах AWS G7e на Blackwell B200, гиперскейлеры изолируют storage через NVMe over Fabrics, но даже там могут быть проблемы с перегруженными storage-нодами. Кстати, именно для снижения зависимости от «шумных соседей» Microsoft и разработала чип Maia 200 с собственной memory subsystem — читайте вот здесь.
Метрики, которые не врут: как диагностировать скрытый bottleneck storage
Забудьте про «cat /proc/diskstats». Для AI-инференса важны:
- DCGM metrics:
dram_active_cycles(< 50% при sm_occupancy > 90% — storage stall). Используйтеdcgmi dmon -e 1001,1002,1004. - Storage IOPS и latency на чтение для размеров запросов, типичных для модели (4KB-128KB). Команда:
fio --name=read --rw=read --bs=128k --size=10G --iodepth=32 --runtime=60. - Per-process I/O с помощью iotop или pidstat — чтобы понять, сколько читает именно worker инференса.
#!/bin/bash
# Быстрая диагностика: сравниваем занятость GPU и пропускную способность storage
# Запускаем параллельно с нагрузкой инференса
dcgmi dmon -e 1001,1002,1004 -d 1000 | awk '{print $1, $2, $3}' > gpu_metrics.txt &
pidstat -d 1 > storage_io.txt &
sleep 30
kill %1 %2
echo "Готово. Анализируем gpu_metrics.txt и storage_io.txt"
Сравните тренды: если dram_active_cycles падает вместе с ростом await в iostat — вы нашли виновника.
RAID-архитектуры для AI: что выбрать
| RAID уровень | Латенси чтения (случайное) | Влияние на инференс | Рекомендация |
|---|---|---|---|
| RAID0 | Низкая | Отлично (нет избыточности) | Только для временных данных |
| RAID10 | Низкая | Хорошо (1:1 репликация) | Лучший выбор для инференса |
| RAID5 | Умеренная (высокая при деградации) | Плохо из-за четности | Избегать |
| RAID6 | Высокая | Катастрофа при деградации | Только для архивов |
Если вам нужна избыточность для долгосрочного хранения моделей — используйте RAID10 на NVMe SSD. Для временных кэшей и весов во время инференса — можно вообще без RAID (данные пересоздаются).
Автоматическое детектирование деградированных узлов
Не ждите, пока пользователи пожалуются. Настройте Health Check с порогами:
- Storage read latency p99 > 2ms для размера 128KB — алерт.
- GPU sm_occupancy > 90% И dram_active_cycles < 40% — алерт «Storage bound».
- Количество ECC-исправлений на NVMe SSD > 10 в день — замена диска.
Пример скрипта для Prometheus alert:
- alert: GPUStarvationByStorage
expr: (dcgm_sm_occupancy{job="dcgm"} > 0.9) and (dcgm_dram_active_cycles{job="dcgm"} < 0.4)
for: 5m
labels:
severity: critical
annotations:
summary: "GPU {{ $labels.gpu }} вероятно ожидает данные от storage"
Обратите внимание: такие метрики обычно не входят в стандартные дашборды cloud-провайдеров. Их нужно собирать самостоятельно. Но это окупается: вы перестанете платить за «пустое» GPU-время.
Облачная альтернатива: почему это не лечится просто «взять больше в облаке»
Многие считают: «Ок, переедем в облако, там всё чики-пуки». Но даже у гиперскейлеров есть подводные камни. Например, instance с gp3 EBS могут иметь лимит throughput, который не масштабируется под GPU. Выбирайте instance с NVMe instance store или FSx for Lustre. Кстати, в материале про энергетический кризис AI упоминалось, что до 20% мощности в дата-центрах теряется на неоптимальных конфигурациях — и storage здесь не исключение.
Для облачного инференса рекомендую придерживаться правила: реплицируйте модель на локальный NVMe каждой GPU-ноды, или используйте NVMe-oF с изолированной полосой пропускания. Тогда проблемы «шумного соседа» по NAS исчезнут.
FAQ: Что ещё проверять, если утилизация GPU высокая, а всё тормозит
Вопрос: В чём разница между «utilization» и «occupancy»?
Utilization — процент времени, когда GPU не в idle. Occupancy — доля активных warp-планировщиков. Высокий utilization при низком occupancy — признак того, что GPU занят управляющими операциями (ожидание данных).
Вопрос: Как быстро проверить влияние storage на инференс на production?
Увеличьте batch size в 2 раза. Если throughput увеличился не пропорционально — bottleneck не GPU. Если latency на чтение из storage выросла — вы нашли проблему.
Не верьте nvidia-smi. Верьте времени до первого токена. И ставьте мониторинг на всю цепочку: GPU -> DMA -> PCIe -> storage controller -> disk. Тогда потерянные деньги перестанут утекать в никуда. Как там говорят старожилы? «Slow storage eats GPU cycles for breakfast, lunch and dinner.»