Решения

Смешанная точность в обучении LLM: BF16/FP16/FP8

Цель. Помочь выбрать формат вычислений под вашу задачу и железо, правильно включить AMP/автокаст, избежать числовых проблем и получить прирост скорости/экономию VRAM без потери качества.

TL;DR:

  • На Ampere/Hopper берите BF16 как дефолт — стабильно, без loss scaling, быстрая математика на Tensor Cores.
  • FP16 всё ещё уместен на старых картах и в узких местах памяти (с GradScaler).
  • FP8 — новый формат Hopper: даёт максимум пропускной способности через Transformer Engine, но требует аккуратной калибрации/валидации; рекомендован продвинутым пользователям.
  • Плюс к этому включайте TF32 (Ampere+) для операций, где оно помогает «бесплатно».

Что такое смешанная точность и зачем она LLM

Смешанная точность (mixed precision) исполняет часть операций в «лёгком» формате (FP16/BF16/FP8), а критичные суммирования/редукции — в FP32. Это снижает затраты на память и ускоряет обучение, при этом сохранность качества обеспечивается автоматическим выбором «где какой формат». В PyTorch это делается через torch.autocast и (для FP16) torch.amp.GradScaler.

Короткий выбор формата

  • BF16 (bfloat16). Такой же диапазон значений, как у FP32, но укороченная мантисса — поэтому как правило не нужен GradScaler; даёт стабильность в обучении трансформеров. На Ampere/Hopper ускоряется Tensor Cores.
  • FP16. Меньше памяти, выше риск «под/переполнения» градиентов — используется вместе с GradScaler (динамический loss scaling).
  • FP8. Введён на H100 (Hopper): ещё больше пропускной способности/экономии памяти, включается через NVIDIA Transformer Engine (TE) и соответствующие бэкенды внимания (cuDNN/FlashAttention‑3). Требует более тщательной валидации качества.
  • TF32. Режим Ampere‑Tensor Cores для FP32‑операций; даёт ускорение «без правок кода» и может быть включён через флаг в PyTorch/HF‑Trainer.

Аппаратная матрица (на что опираться)

  • Ampere (A100/RTX 30/L40): Tensor Cores для FP16, BF16, TF32. BF16/FP16 работают на схожей скорости на Tensor Cores.
  • Hopper (H100): всё вышеперечисленное + FP8 (через Transformer Engine).

Мини‑рецепты: как включить в вашем тренинге

A) BF16 в PyTorch (без GradScaler)

				
					model.train()
for batch in loader:
    with torch.autocast(device_type="cuda", dtype=torch.bfloat16):
        loss = model(**batch).loss
    loss.backward()
    optimizer.step(); optimizer.zero_grad(set_to_none=True)

				
			

autocast выбирает формат операций автоматически; BF16 обычно не требует масштабирования градиента.

B) FP16 + GradScaler

				
					scaler = torch.amp.GradScaler(enabled=True)
for batch in loader:
    with torch.autocast(device_type="cuda", dtype=torch.float16):
        loss = model(**batch).loss
    scaler.scale(loss).backward()
    scaler.step(optimizer); scaler.update()
    optimizer.zero_grad(set_to_none=True)

				
			

GradScaler предотвращает «занижение» градиентов в FP16 и повышает устойчивость.

C) Включить TF32 (ускорение «поверх»)

				
					torch.backends.cuda.matmul.allow_tf32 = True

				
			

Либо через аргументы Trainer в HF: TrainingArguments(tf32=True).

D) FP8 через Transformer Engine (H100)

Высокоуровневый путь — заменить стандартные слои на модули TE или активировать автосмешивание TE, чтобы матмульты/внимание шли в FP8 c нужными калибровками. Смотрите «FP8 primer» и примеры TE.

Производительность и экономия памяти

  • BF16/FP16 ускоряют математику на Tensor Cores и уменьшают объём активаций, что часто напрямую увеличивает пропускную способность шагов. На Ampere это «базовый» путь ускорения DL‑тренинга.
  • FP8 (H100) повышает throughput внимания/матмультов ещё заметнее; например, в FlashAttention‑3 на Hopper заявлено ~1.5–2.0× ускорение против предыдущего поколения (и вплоть до ~PFLOPs/s в FP8).

Числовая стабильность и типичные настройки

  • FP16: включайте GradScaler, grad_clip, проверяйте падение лосса без «ступенек» — признак корректной шкалы.
  • BF16: обычно «ставится и работает», но всё равно держите grad_clip и мониторинг NaN/Inf.
  • FP8: используйте рекомендуемые бэкенды внимания (cuDNN attention с FP8 или FlashAttention‑3 на H100) и следуйте гайдам TE по диапазонам/калибровке. Не переходите на FP8 без сравнения качества на вашем вал‑корпусе.

LLM‑специфика: где прячется выигрыш

  • Attention‑ядра. Современные реализации (cuDNN attention / FlashAttention‑2/3) дают основной прирост; они работают в BF16/FP16, а на H100 — и в FP8.
  • KV‑кэш и длина контекста. Память и время растут с контекстом; смешанная точность снижает объём активаций и требования к HBM, но контролируйте стабильность при длинных L (наблюдайте перплексию/регрессии).
  • Комбинации с FSDP/ZeRO. Смешанная точность хорошо сочетается с шардированием параметров/стейтов; выбирайте BF16 как «базу», добавляйте grad‑checkpointing. См. страницу по FSDP/DeepSpeed.

Быстрый чек‑лист выбора

  1. Железо Ampere/Hopper? → начинайте с BF16.
  2. Старая карта / нужен экстремальный выигрыш памяти?FP16 + GradScaler.
  3. H100 и критичен максимум TPS? → пробуйте FP8 через Transformer Engine, обязательно валидируя качество.
  4. Поставьте TF32 как дополнение для матриц FP32.

Траблшутинг

  • NaN/Inf в градиентах (FP16). Понизить lr, включить/усилить GradScaler, добавить grad_clip, проверить датасет на экстремальные значения.
  • Граф «зубцами» / неравномерная скорость. Убедитесь, что «тяжёлые» операции действительно попадают под autocast; проверьте, что каст не выключен в кастомных слоях.
  • Деградация качества (FP8). Перекалибровать/сузить области FP8, откатиться на BF16 для чувствительных слоёв внимания/MLP; сравнить валидацию до/после.

Навигация по смежным страницам