Решения

Оптимизация на GPU: смешанная точность, профайлинг и I/O

Цель. Дать практичные приёмы, которые быстро повышают скорость и снижают стоимость: смешанная точность (BF16/FP16), оптимизация памяти (pinned memory, чекпоинтинг), ускорение I/O и базовый профайлинг. Подходит для обучения, инференса, CV/рендера и HPC.

Быстрые результаты за 10 минут

Если времени мало — начните с этих переключателей:

Смешанная точность (BF16/FP16).

 • Для A100/H100 чаще всего рационален BF16 (без скейлера).
• Для карт с FP16 — autocast + GradScaler (для обучения).
• Для инференса — autocast достаточно.

TF32 для матричных операций (Ampere+).

 В обучении CNN/трансформеров TF32 почти всегда даёт прирост без заметной потери качества.

Формат памяти channels_last (CNN).

Ускоряет свёртки: model.to(memory_format=torch.channels_last) и храните тензоры в том же формате.

CuDNN autotune для фиксированных размеров.

torch.backends.cudnn.benchmark = True — если входные размеры стабильны.

DataLoader: pinned memory + потоки.

 pin_memory=True, num_workers>0, persistent_workers=True, prefetch_factor=2–4.

Компиляция графа (PyTorch 2.x).

torch.compile(model) как простой способ убрать питоновские накладные расходы (особенно в инференсе).

Смешанная точность: BF16/FP16/FP8 — когда и зачем

Лучший баланс «скорость/стабильность» для обучения LLM/CV; обычно без GradScaler.

Требует аккуратности: используйте autocast и GradScaler в обучении.

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

Мини‑шаблоны:

Обучение с BF16:

				
					with torch.autocast(device_type="cuda", dtype=torch.bfloat16):
    loss = model(inputs).loss
    loss.backward()
				
			

Обучение с FP16:

				
					scaler = torch.cuda.amp.GradScaler()
with torch.autocast("cuda", dtype=torch.float16):
    loss = model(inputs).loss
scaler.scale(loss).backward()
scaler.step(optimizer); scaler.update()
				
			

Память и стабильность: как влезть в VRAM

  • Gradient checkpointing. Вычисляйте часть активаций повторно, экономя VRAM; особенно полезно на LLM и больших CNN.
  • Gradient accumulation. Эмулируйте большой батч за несколько шагов при меньшем VRAM.
  • Fused‑ядра и оптимизаторы. Fused Adam/Adan/Lion снижают накладные расходы.
  • Offload/ZeRO/FSDP. Для гигантских моделей переносите часть состояния на CPU/диск или распределяйте по данным/параметрам (см. /solutions/llm-training/fsdp-deepspeed/).
  • MIG/партиционирование (A100/H100). Когда нужен предсказуемый QoS под много мелких задач (см. /solutions/mig/).

I/O и подготовка данных: чтобы GPU не простаивал

Симптом: загрузка GPU < 70%, при этом CPU/Disk заняты.

  • Pinned memory + prefetch. Включайте закрепление памяти и заблаговременную подачу батчей.
  • Persistent workers. Исключают перезапуски процессов загрузчиков между эпохами.
  • Шардирование датасетов и стриминг. Подача через tar‑шарды/веб‑стрим снижает накладные расходы на мелкие файлы.
  • NVMe кэш/ramdisk для «горячих» данных. Перенесите часто используемые выборки ближе к GPU.
  • Аугментации на GPU. Перенесите тяжёлые преобразования в GPU‑поток (там, где это уместно).

Инференс: как получить больше TPS и ниже латентность

  • Движок под задачу.
    • Универсальный высокоскоростной сервинг — см. /solutions/llm-inference/vllm/.
    • Минимальная латентность и компиляция графа — /solutions/llm-inference/tensorrt-llm/.
    • Готовый прод‑сервер — /solutions/llm-inference/tgi/.
  • Квантизация. INT8/INT4/FP8 — снижает VRAM и ускоряет инференс (см. /solutions/llm-inference/quantization/).
  • Пакетирование запросов. Грамотный батчинг и настройка очередей резко повышают TPS.
  • KV‑кэш, attention‑оптимизации. Ускоряют генерацию длинных последовательностей.

Профилирование: быстрый ритуал на 15 минут

  1. Снимите базовую метрику: wall‑time на эпоху/100 итераций, загрузку GPU (nvidia-smi), пропускную способность (samples/sec или токены/сек).
  2. Разделите на Compute vs Data. Замерьте, сколько времени уходит на forward/backward/optimizer.step и сколько — на DataLoader/аугментации/диск/сеть.
  3. Локализуйте «узкое место»:
    • если GPU «ждёт» — идите в раздел I/O;
    • если GPU «упёрся» в память — включайте mixed precision/accumulation/checkpointing;
    • если «упёрся» в вычисления — пробуйте torch.compile, fused‑операции, специализированные ядра.
  4. Внесите 1–2 изменения и перепрофилируйте. Двигайтесь итеративно, фиксируя прирост.

Чек‑лист перед «боем»

  • Смешанная точность выбрана (BF16/FP16/FP8) и проверена на стабильность лосса/метрик.
  • DataLoader: pin_memory, num_workers, persistent_workers, prefetch_factor настроены.
  • Batch size и grad accumulation подобраны под VRAM; при необходимости включён checkpointing.
  • torch.backends.cudnn.benchmark включён только для фиксированных размеров.
  • Для инференса выбран профиль: vLLM / TensorRT‑LLM / TGI + стратегия батчинга.
  • Логи метрик и времени записываются; есть эталонная «до/после».

Типовые рецепты по задачам

LLM — обучение. BF16 + checkpointing + grad accumulation; при больших моделях — FSDP/ZeRO.
LLM — инференс. Выберите движок (vLLM или TensorRT‑LLM) + квантизация + грамотный батчинг.
CV — обучение. channels_last + TF32 (или BF16/FP16) + аугментации на GPU.
Генерация изображений/видео. Параллельный рендер/батчи, вывод артефактов на NVMe, статические размеры.
HPC. Синхронизация и раскладка данных по узлам, профилирование I/O, NUMA‑аффинность.

Частые ошибки

  • benchmark=True при переменных размерах → неоптимальные алгоритмы и дерганая скорость.
  • GradScaler с BF16 → лишние накладные расходы без пользы.
  • Пустые воркеры DataLoader → GPU простаивает, хотя «карта занята».
  • Слишком большой диск «на всякий случай» → растёт стоимость хранения.
  • Батчи «на грани VRAM» → флуктуации и OOM; держите небольшой запас.