FP8 и BF16: выбор формата вычислений

Задача страницы. Помочь выбрать формат чисел (FP8/BF16/FP16/FP32) под обучение и инференс на GPU в https://cloudcompute.ru: когда и как включать смешанную точность, где уместен FP8, как контролировать стабильность и экономику без потери качества.

TL;DR

  • BF16 — дефолт для обучения: широкая поддержка, стабильные градиенты, минимальная потеря качества. FP16 — только при явной необходимости и грамотной настройке loss scaling.
  • FP8 — для ускорения матмулов/MLP/Attention: хранение активаций/весов в FP8 с аккумулированием в BF16/FP32 даёт прирост throughput и экономию VRAM. Требует калибрации amax и исключений (LayerNorm/Softmax в BF16).
  • Гибрид: MHA/MLP в FP8, всё чувствительное (нормировки, редукции, софтмакс, логиты, целевые функции) — в BF16.
  • Инференс: FP8 + INT8‑кэш/KV даёт лучшую цену за токен; TTFT (time‑to‑first‑token) и стабильность — за счёт BF16 в узких местах.
  • Наблюдаемость — обязательна: NaN/Inf, amax‑гистограммы, p50/p95 латентности; см. https://cloudcompute.ru/solutions/monitoring-logging/ и https://cloudcompute.ru/solutions/llm-inference/observability/.
  • Экономика: считайте Cost_per_1M_tokens, Cost_per_epoch, Cost_per_image от c_gpu, U (целевая загрузка) и TPS/FPS; см. https://cloudcompute.ru/solutions/cost-planner/ и https://cloudcompute.ru/solutions/throughput-vs-latency/.
  • Мульти‑GPU: FSDP/ZeRO с BF16 — база; FP8 в матрицах — надстройка (см. https://cloudcompute.ru/solutions/multi-gpu/).
  • Режимы: On‑Demand — стабильность/латентность важнее, больше BF16; Interruptible — массовая генерация, агрессивнее FP8 (чанки ≤ 120 сек), см. https://cloudcompute.ru/solutions/interruptible-patterns/.

Сценарии

  • Обучение больших трансформеров: BF16 (веса/активации) + выборочно FP8 в GEMM/Attention; оптимайзер/аккумуляторы — FP32.
  • LoRA/QLoRA‑дообучение: хранение адаптеров в 16‑бит, вычисления в BF16, иногда FP8 на форварде для MLP.
  • Инференс LLM: префилл/декод в FP8 (актив/веса) с аккумулированием в BF16; LayerNorm/Softmax/KV‑редукции — BF16; KV‑кэш INT8/FP8.
  • CV (детекция/сегментация/диффузия): обучение — BF16; инференс — FP16/BF16, для пост‑процессинга/детализации BF16; иногда FP8 на backbone.
  • Гео/CV‑тайлы/видеоаналитика: FP8 на feature‑экстракции, BF16 в декодерах/постпроцессе; NVDEC/NVENC — отдельно (см. https://cloudcompute.ru/solutions/performance-tuning/).
  • HPC‑фрагменты в ML‑пайплайн: редукции/статистика — BF16/FP32, матмулы — FP8.

Архитектуры/пайплайны (ASCII) A) Обучение (BF16 + выборочно FP8)

Даталоадер → Аугментации → [Autocast BF16]
 → (Attention/MLP: FP8 GEMM, Accum BF16)
 → Нормировки/Softmax: BF16
 → Потери: FP32
 → Backward: Grad Scale / Clip
 → Оптимайзер: FP32 master weights
 → FSDP/ZeRO (шардинг, чекпоинт)
Мониторинг: loss, NaN/Inf, amax, step_time(p50/p95), gpu_util/hbm

B) Инференс (FP8 приоритетно, BF16 в «хрупких» местах)

Запрос → Токенизация → Префилл (FP8 GEMM, Accum BF16)
 → KV-кэш (INT8/FP8) → Декод (loop)
 → Нормировки/Softmax(logits): BF16
 → Постпроцессинг/стриминг SSE/WebSocket
Метрики: TTFT, TPS(tok/s), p95 latency, drop, gpu_util/hbm

См. общие тюнинги: https://cloudcompute.ru/solutions/performance-tuning/ и компромиссы: https://cloudcompute.ru/solutions/throughput-vs-latency/.

Профили GPU / VRAM / ориентиры скорости

**Профиль** **Видеопамять** **Рекоменд. формат обучения** **Рекоменд. формат инференса** **Ориентиры скорости\*** **Параллельные задачи/GPU** **Режим**
**24 ГБ (Compact)** 24 ГБ BF16 (всё), FP8 точечно в MLP малых моделей FP8 префилл/декод, BF16 LN/Softmax +1.2–1.6× к FP16 при FP8‑GEMM 1–2 On‑Demand/Interruptible
**48 ГБ (Balanced)** 48 ГБ BF16 база, FP8 на Attention/MLP средних моделей FP8 на матрицах, BF16 на «хрупких» +1.5–2.0× к FP16, −30–40% VRAM 2–3 Оба
**80 ГБ (HQ)** 80 ГБ BF16 (полномасштабные батчи), FP8 выборочно на 30B+ FP8 повсеместно + INT8 KV +1.8–2.5× к FP16, −35–50% VRAM 3–4 Оба

*Ориентиры носят инженерный характер и зависят от модели/секвенции/батча.

Конфиги и скелеты

1) Общий YAML‑флаг для формата вычислений

compute:
 dtype: "bf16" # bf16 | fp16 | fp8
 accum_dtype: "fp32" # для оптимайзера/редукций
 fp8:
 enabled: true
 format: "e4m3" # e4m3 | e5m2
 amax_calibration_steps: 200
 exclude_ops: ["layernorm", "softmax", "logits"]
 grad:
 scaling: "dynamic" # dynamic | static
 clip_norm: 1.0
 kv_cache:
 dtype: "int8" # int8 | fp8 | bf16

2) PyTorch: BF16 обучение (стабильная база)

import torch
from torch import nn, optim
model = nn.TransformerEncoderLayer(d_model=1024, nhead=16, batch_first=True).cuda()
optimizer = optim.AdamW(model.parameters(), lr=2e-4)
scaler = torch.cuda.amp.GradScaler(enabled=False) # BF16 не требует loss scaling
model.train()
for step, (x, y) in enumerate(loader):
 x, y = x.cuda(non_blocking=True), y.cuda(non_blocking=True)
 with torch.autocast(device_type="cuda", dtype=torch.bfloat16):
 logits = model(x)
 loss = nn.functional.cross_entropy(logits.view(-1, logits.size(-1)), y.view(-1))
 optimizer.zero_grad(set_to_none=True)
 loss.backward()
 torch.nn.utils.clip_grad_norm_(model.parameters(), 1.0)
 optimizer.step()

3) PyTorch: включение FP8 там, где поддерживается

import torch
from torch import nn
# Проверяем поддержку float8 dtypes
has_fp8 = hasattr(torch, "float8_e4m3fn") and hasattr(torch, "float8_e5m2")
FP8_W = getattr(torch, "float8_e4m3fn", None) # веса/активации
ACCUM = torch.bfloat16
class MlpBlock(nn.Module):
 def __init__(self, d):
 super().__init__()
 self.fc1 = nn.Linear(d, 4*d, bias=False, dtype=ACCUM)
 self.fc2 = nn.Linear(4*d, d, bias=False, dtype=ACCUM)
 self.act = nn.GELU()
 def forward(self, x):
 if has_fp8:
 # Пример: хранение активаций в FP8, вычисления — с аккумулированием в BF16
 x_fp8 = x.to(FP8_W) # квантизация входа
 h = (self.fc1(x_fp8.to(ACCUM))) # де-квантизация → GEMM (ACCUM)
 else:
 h = self.fc1(x)
 h = self.act(h)
 if has_fp8:
 h_fp8 = h.to(FP8_W)
 y = self.fc2(h_fp8.to(ACCUM))
 else:
 y = self.fc2(h)
 return y

Замечание: в проде используйте реализованные FP8‑слои вашего фреймворка/библиотек. Общий принцип сохраняется: хранение FP8, вычисление/аккумуляция — BF16/FP32, исключая чувствительные операции.

4) Инференс: гибрид FP8/BF16 и стриминг SSE

import torch
from fastapi import FastAPI
from fastapi.responses import StreamingResponse
app = FastAPI()
model.eval()
def generate(prompt_ids, max_new_tokens=128):
 with torch.no_grad(), torch.autocast("cuda", dtype=torch.bfloat16):
 # Префилл в FP8 (если доступно)
 # ... подготовка KV-кэша (int8/fp8)
 for _ in range(max_new_tokens):
 logits = model(prompt_ids) # внутри: FP8 GEMM + BF16 LN/Softmax
 next_id = torch.argmax(logits[:, -1], dim=-1, keepdim=True)
 yield int(next_id)
 prompt_ids = torch.cat([prompt_ids, next_id], dim=1)
@app.get("/events")
def sse(prompt: str):
 token_ids = tokenize(prompt).cuda()
 def stream():
 for tok in generate(token_ids):
 yield f"data: {tok}nn"
 return StreamingResponse(stream(), media_type="text/event-stream")
``` ## **Наблюдаемость, метрики, алерты**

См. <https://cloudcompute.ru/solutions/monitoring-logging/> и <https://cloudcompute.ru/solutions/llm-inference/observability/>.

**Обучение**

- train\_step\_time\_ms (p50/p95), throughput\_tokens\_s, data\_wait\_ms
- loss, grad\_norm, nan\_inf\_count, overflow\_steps
- amax\_histogram (по слоям FP8), activation\_range\_saturation\_pct
- GPU: gpu\_util\_pct, gpu\_mem\_used\_gb (HBM), sm\_efficiency\_pct, pcie\_tx\_mb\_s

**Инференс**

- ttft\_ms (p50/p95), tps\_tok\_s, latency\_ms (p50/p95), queue\_depth
- kv\_cache\_bytes, kv\_dtype, cache\_hit\_ratio
- Качество: целевые метрики (перплексия/accuracy/PSNR и т.п.) на контрольном наборе

**Алерты**

- nan\_inf\_count &gt; 0 → немедленно выключить FP8 на соответствующих слоях, включить проверки диапазона.
- activation\_range\_saturation\_pct &gt; 1% → увеличить динамику квантизации (ротация amax).
- ttft\_ms(p95) вне SLO → вернуть часть путей в BF16, уменьшить батч; см. <https://cloudcompute.ru/solutions/throughput-vs-latency/>.
- gpu\_mem\_used\_gb / vram &gt; 0.9 → уменьшить длину контекста/батч или KV‑dtype.

## **Экономика и формулы**

Обозначения: c\_gpu — цена GPU/час; U — целевая загрузка; N\_gpu — число GPU; TPS — токены/сек на GPU; t\_h — часы; S — ускорение относительно FP16; M\_mem — VRAM, R\_mem — экономия памяти.

**Инференс (цена за 1k/1M токенов)**

EffCostPerHour = (c\_gpu \* N\_gpu) / U

TokensPerHour = TPS \* 3600 \* N\_gpu

Cost\_per\_1000\_tok = EffCostPerHour / (TokensPerHour / 1000)

Cost\_per\_1M\_tok = EffCostPerHour / (TokensPerHour / 1\_000\_000)

**Влияние FP8**

TPS\_fp8 ≈ TPS\_fp16 \* S

VRAM\_fp8 ≈ M\_mem \* (1 - R\_mem)

**Обучение (цена эпохи)**

Tokens\_epoch = N\_samples \* seq\_len

Train\_tokens\_per\_hour = TPS\_train \* 3600 \* N\_gpu

Cost\_per\_epoch = EffCostPerHour \* (Tokens\_epoch / Train\_tokens\_per\_hour)

**KV‑кэш**

KV\_bytes ≈ N\_layers \* 2 \* heads \* head\_dim \* seq\_len \* dtype\_bytes

→ При FP8/INT8 dtype\_bytes снижаются, растёт вместимость контекста на ту же VRAM.

Планируйте параметры и профили на <https://cloudcompute.ru/solutions/cost-planner/>.

**Безопасность/политики**

- **Детерминизм и воспроизводимость**: фиксируйте версии образов/драйверов/библиотек, seed; логируйте dtype‑решения в чекпоинтах.
- **Защита данных**: контроль доступа к датасетам/валидационным сетам; разделение тренировочных/продовых секретов (см. <https://cloudcompute.ru/solutions/security/>).
- **PII**: если обучаете на пользовательских данных — маскирование, ретеншн; отдельные среды для приватных наборов.
- **Политики прерывания**: для Interruptible — чекпоинты ≤ 120 сек и идемпотентные задачи (см. <https://cloudcompute.ru/solutions/interruptible-patterns/>).

**Траблшутинг**

<table><tbody><tr><td>**Симптом**

</td><td>**Причина**

</td><td>**Решение**

</td></tr><tr><td>NaN/Inf в лоссе на FP8

</td><td>Пересатурация диапазона, плохая калибровка amax

</td><td>Временно переведите слой в BF16, перезапустите калибровку на 100–200 шагов, включите range‑статистику.

</td></tr><tr><td>Качество просело на валидации

</td><td>FP8 в чувствительных узлах (LN/Softmax/Logits)

</td><td>Исключите эти операции из FP8; оставьте BF16/FP32.

</td></tr><tr><td>TTFT вырос, TPS упал

</td><td>Микробатчинги/очереди перегружены

</td><td>Уменьшите batch/beam, увеличьте параллелизм по запросам; проверьте PCIe/NVLink.

</td></tr><tr><td>OOM при длинных контекстах

</td><td>KV‑кэш в BF16/FP16

</td><td>Переключите KV‑dtype на INT8/FP8, уменьшите seq\_len, используйте «paged‑KV».

</td></tr><tr><td>Тренировка флапает (нестабильна)

</td><td>FP16 с недостаточным loss scaling

</td><td>Перейдите на BF16; включите dynamic scaling или снизьте LR.

</td></tr><tr><td>Перфоманc не растёт на FP8

</td><td>Узкое место не в GEMM

</td><td>Профилируйте: возможно, софтмакс/редукции/даталоадер — тюнинг I/O и редукций.

</td></tr><tr><td>Разные результаты между нодами

</td><td>Несовпадение dtype и seed

</td><td>Зафиксируйте конфиг, проверьте автокаст и версии пакетов.

</td></tr></tbody></table>

**Как запустить в cloudcompute.ru**

1. Выберите **шаблон** (Docker/SSH/Jupyter) на <https://cloudcompute.ru/solutions/templates/>.
2. Определите **режим**: On‑Demand (интерактивный инференс/демо) или Interruptible (массовая генерация/обучение чанками). См. <https://cloudcompute.ru/solutions/interruptible-patterns/>.
3. Подберите **профиль GPU**: 24 ГБ (Compact), 48 ГБ (Balanced), 80 ГБ (HQ). См. таблицу профилей выше.
4. В образ/конфиг добавьте **dtype‑флаги** (BF16 база; FP8 — точечно, с калибровкой).
5. Настройте **наблюдаемость**: метрики качества/латентности/amax, GPU util/HBM — см. <https://cloudcompute.ru/solutions/monitoring-logging/> и <https://cloudcompute.ru/solutions/llm-inference/observability/>.
6. Для мульти‑обучения включите **FSDP/ZeRO** — см. <https://cloudcompute.ru/solutions/multi-gpu/>.
7. Сбалансируйте **throughput↔latency** под вашу SLO — см. <https://cloudcompute.ru/solutions/throughput-vs-latency/> и <https://cloudcompute.ru/solutions/performance-tuning/>.
8. Проверьте **секьюрити/ретеншн** конфигов/датасетов — <https://cloudcompute.ru/solutions/security/>.

**Чек‑лист перед продом**

- Обучение в BF16, исключения (LN/Softmax/Logits) — BF16/FP32, FP8 — только на матрицах после калибровки.
- amax‑калибровка выполнена; activation\_range\_saturation\_pct ≤ 1%.
- На инференсе соблюдены SLO: ttft\_ms(p95), tps\_tok\_s, latency\_ms(p95).
- KV‑кэш в INT8/FP8 при длинных контекстах; OOM не воспроизводится.
- GPU util 60–85%, запас VRAM ≥ 20%; отсутствуют переполнения очередей I/O.
- Метрики/алерты заведены; NaN/Inf ловятся и останавливают пайплайн.
- Экономика подтверждена: Cost\_per\_1M\_tokens/Cost\_per\_epoch через <https://cloudcompute.ru/solutions/cost-planner/>.
- Конфиги dtype/версии библиотек зафиксированы в CI/CD (см. <https://cloudcompute.ru/solutions/containers-ci-cd/>).
- Политики безопасности/ретеншна — применены (<https://cloudcompute.ru/solutions/security/>).

**Навигация**

- Хаб «Решения»: <https://cloudcompute.ru/solutions/>
- Шаблоны запусков: <https://cloudcompute.ru/solutions/templates/>
- Планирование стоимости: <https://cloudcompute.ru/solutions/cost-planner/>
- Тюнинг производительности: <https://cloudcompute.ru/solutions/performance-tuning/>
- Throughput vs Latency: <https://cloudcompute.ru/solutions/throughput-vs-latency/>
- Multi‑GPU/Multi‑node: <https://cloudcompute.ru/solutions/multi-gpu/>
- Хранилища и данные: <https://cloudcompute.ru/solutions/storage-data/>
- Наблюдаемость/логи: <https://cloudcompute.ru/solutions/monitoring-logging/>
- Observability для LLM/сервисов: <https://cloudcompute.ru/solutions/llm-inference/observability/>
- Interruptible‑паттерны: <https://cloudcompute.ru/solutions/interruptible-patterns/>
- Triton Inference Server: <https://cloudcompute.ru/solutions/triton-inference-server/>
- Контейнеры и CI/CD: <https://cloudcompute.ru/solutions/containers-ci-cd/>

Готовы запустить?

Запустить GPU-сервер