FP8
FP8 — это 8-битный формат чисел с плавающей точкой с вариантами E4M3 и E5M2, который вдвое сокращает расход памяти по сравнению с 16-битным форматом и удваивает пропускную способность матричных вычислений на поддерживаемых GPU.
FP8 — это 8-битный формат чисел с плавающей запятой, используемый для обучения и запуска нейронных сетей с вдвое меньшим расходом памяти и вдвое меньшим объёмом передаваемых данных по сравнению с 16-битными форматами. Как и в любом формате чисел с плавающей запятой, каждое значение содержит бит знака, биты экспоненты, задающие его диапазон, и биты мантиссы, задающие его точность, однако при общей разрядности всего в восемь бит приходится идти на серьёзные компромиссы и по диапазону, и по точности. Инженеры NVIDIA, Arm и Intel определили два стандартных варианта — E4M3 и E5M2 — в статье Форматы FP8 для глубокого обучения, опубликованной в сентябре 2022 года, и подтвердили возможность обучения с их помощью языковых моделей с числом параметров до 175 миллиардов. На GPU с тензорными ядрами FP8, например на Hopper H100 от NVIDIA, представленном в 2022 году, пропускная способность операций матричного умножения в FP8 вдвое выше, чем при использовании FP16 или BF16.
E4M3 и E5M2#
Два варианта по-разному распределяют семь битов, не считая бита знака:
- E4M3: Четыре бита экспоненты и три бита мантиссы. Формат отказывается от бесконечностей и использует единственный шаблон NaN, чтобы достичь максимального значения 448; он подходит для весов и активаций при прямом проходе.
- E5M2: Пять битов экспоненты и два бита мантиссы, со специальными значениями по соглашениям IEEE 754. Максимальное значение — 57 344, шаги крупнее; формат подходит для градиентов, величины которых меняются в более широком диапазоне.
Оба формата округляют малые значения до нуля, а большие ограничивают, поэтому тензоры FP8 обычно снабжают масштабным коэффициентом, который переводит значения в представимый диапазон. Преобразование значений размером с градиент с масштабированием и без него показывает, зачем это нужно:
import torch
torch.manual_seed(0)
grads = torch.randn(10_000) * 1e-4 # gradient-sized values, far below 1
e4m3, e5m2 = torch.float8_e4m3fn, torch.float8_e5m2
print(f"E4M3 max {torch.finfo(e4m3).max:g}, E5M2 max {torch.finfo(e5m2).max:g}")
# Per-tensor scaling maps the largest magnitude onto the E4M3 maximum before casting
scale = torch.finfo(e4m3).max / grads.abs().max()
results = {
"E4M3 direct": grads.to(e4m3).float(),
"E5M2 direct": grads.to(e5m2).float(),
"E4M3 scaled": (grads * scale).to(e4m3).float() / scale,
}
for name, restored in results.items():
zeros = (restored == 0).float().mean()
error = ((restored - grads).abs() / grads.abs()).median()
print(f"{name}: {zeros:.0%} rounded to zero, median relative error {error:.1%}")При прямом преобразовании в E4M3 100% значений округляется до нуля; более широкий диапазон E5M2 сохраняет большинство значений, обеспечивая 6.4% медианной относительной ошибки и теряя 7%; предварительное масштабирование позволяет E4M3 сохранить все значения при медианной ошибке 2.2%. PyTorch также предоставляет float8_e4m3fnuz и float8_e5m2fnuz — варианты, используемые ускорителями AMD MI300: в них отсутствует отрицательный ноль, смещён экспоненциальный порядок, а максимальное значение E4M3 ограничено 240. Поэтому модель FP8 не обязательно переносима между оборудованием разных производителей.
Стратегии масштабирования#
Единый коэффициент масштаба для всего тензора не работает, когда несколько выбросов задают максимум и приближают все остальные значения к нулю; это часто происходит с активациями трансформера. Способы масштабирования различаются степенью детализации:
- Отложенное масштабирование на уровне тензора: Transformer Engine от NVIDIA выбирает масштаб каждого тензора по максимальным значениям, наблюдавшимся на недавних шагах обучения, поэтому повторно обрабатывать данные не нужно.
- Блочное масштабирование: DeepSeek-V3 масштабировала активации по тайлам размером 1 × 128 значений, а веса — по блокам 128 × 128; команда сообщила о первой проверке обучения FP8 на чрезвычайно крупной модели размером 671 миллиард параметров.
- MXFP8: Формат микромасштабирования Open Compute Project использует общий масштаб — степень двойки — для каждых 32 значений; GPU NVIDIA Blackwell выполняют его аппаратно.
Результаты матричных умножений накапливаются с более высокой точностью, а чувствительные или дешёвые в вычислительном отношении слои, например нормализация, softmax и основные веса оптимизатора, остаются в BF16 или FP32. Поэтому FP8 — лишь часть схемы смешанной точности.
FP8 при обучении и инференсе#
Для обучения Transformer Engine от NVIDIA и TorchAO заменяют линейные слои версиями FP8, сохраняя основные веса в формате более высокой точности. При инференсе движки обслуживания моделей хранят веса модели и KV-кэш больших языковых моделей в FP8: по сравнению с 16-битными форматами это вдвое снижает расход памяти и позволяет обрабатывать больше одновременных запросов. TensorRT также создаёт движки FP8 для GPU с FP8 Tensor Cores. Чтобы формат приносил пользу, нужна аппаратная поддержка: NVIDIA A100 выполняет операции FP16, BF16 и INT8 на Tensor Cores, но не поддерживает FP8, тогда как GPU Ada Lovelace, Hopper и Blackwell, а также серия MI300 от AMD поддерживают его.
FP8 занимает промежуточное положение между соседними форматами:
- FP16, или половинная точность: Вдвое больше битов, 10 бит мантиссы и достаточно широкий диапазон для большинства задач инференса без масштабирования на уровне тензора.
- FP4: Ещё вдвое меньше битов; точность сохраняется за счёт масштабирования с высокой детализацией по блокам.
- INT8: Другой 8-битный формат с 256 равномерно распределёнными уровнями вместо экспоненциального распределения FP8. Для него нужны калиброванные масштабы, зато он работает на гораздо большем количестве оборудования, в том числе на большинстве CPU и NPU.
Ultralytics YOLO26 использует подход INT8 для 8-битного инференса: экспорт с quantize=8 в режиме экспорта в такие форматы, как TensorRT и OpenVINO, запускает посттренировочную квантизацию модели, которая калибрует масштабы на изображениях из набора данных data; модель же, дообученная с помощью quantize=8 посредством квантизационно-осведомлённого обучения, экспортируется в TensorRT с выученными диапазонами и не требует калибровки.










