Линейка для чисел: как я собрал каталог из 83 форматов с плавающей точкой — и почему у каждого есть честная статус-метка. bfloat16.. bfloat16. floating point.. bfloat16. floating point. fp8.. bfloat16. floating point. fp8. GoldenFloat.. bfloat16. floating point. fp8. GoldenFloat. P3109.. bfloat16. floating point. fp8. GoldenFloat. P3109. rtl.. bfloat16. floating point. fp8. GoldenFloat. P3109. rtl. квантизация.. bfloat16. floating point. fp8. GoldenFloat. P3109. rtl. квантизация. Машинное обучение.. bfloat16. floating point. fp8. GoldenFloat. P3109. rtl. квантизация. Машинное обучение. числа с плавающей точкой.. bfloat16. floating point. fp8. GoldenFloat. P3109. rtl. квантизация. Машинное обучение. числа с плавающей точкой. числовые форматы.

Это вторая статья про проект GoldenFloat. Первая была про φ-лестницу форматов и троичную «Сетунь». Здесь — про инструмент, который вырос из той работы: единый, машинно-проверяемый каталог форматов чисел, где у каждого формата есть точная разрядка битов, статус-метка и битовый отпечаток. И про главную дисциплину этой работы: у каждого формата есть честная статус-метка того, насколько он проверен — вплоть до границы, где формула ещё работает, а проверенного железа уже нет.

Любой, кто хоть раз дебажил несовпадение точности между двумя реализациями нейросети, знает это чувство: один и тот же matmul на двух устройствах даёт разный результат, и непонятно — это баг, или просто bf16 так округлил, или вообще другой формат подкрался. Инженеры на разных концах конвейера меряют один и тот же результат разными линейками — и корректная деталь читается как брак.

Идея каталога простая: сделать одну линейку с точными насечками. Для каждого числового формата — сколько бит на знак, экспоненту, мантиссу; чему равно смещение (bias); как кодируются inf, NaN, субнормальные; где лежит «якорная» точка 3.0. Не описание словами, а машинный источник истины (SSOT), из которого автоматически генерируются Markdown, JSON, Python, Rust, C — и даже RTL для кремния.

Препринт по каталогу: arXiv:2606.09686.

Обложка: Golden Ruler — каталог из 83 числовых форматов

Обложка: Golden Ruler — каталог из 83 числовых форматов

Оглавление

Зачем вообще каталог форматов

За последние десять лет зоопарк числовых форматов в машинном обучении вырос взрывообразно. Раньше хватало float32 и float16. Потом появились bfloat16, TF32, FP8 в двух вариантах (E4M3 и E5M2), FP6, FP4, микромасштабируемые MXFP-форматы с общей экспонентой, NF4 из мира QLoRA, posit’ы, takum’ы, логарифмические LNS. У каждого — свой компромисс «диапазон против точности», свои правила округления, свои граничные случаи.

Проблема в том, что спецификации этих форматов разбросаны по статьям, стандартам и кодовым базам, и нередко противоречат друг другу даже внутри одной библиотеки. Классический пример: что делает FP8 E4M3 при переполнении на кодировании? По одной конвенции (tt-metal, AMD) — насыщается до максимума 448.0; по другой (JAX, TPU) — уходит в NaN. Стандарт OCP MX разрешает оба варианта. И пока вы не зафиксируете, какой именно у вас, «совпадает ли результат» — вопрос не проверяемый, а вкусовой.

Каталог отвечает на это так: один файл-спецификация, из которого всё остальное выводится механически. Если спека и сгенерированный декодер разойдутся — это ловит CI, а не человек на ревью.

Что внутри: 83 формата в 13 кластерах

На момент написания статьи живой источник истины (specs/numeric/formats_catalog.t27) содержит 83 формата, сгруппированных в 13 кластеров. Вот разбивка (число проверено на свежем клоне репозитория — это важно, и ниже я объясню почему):

Кластер

Кол-во

Что внутри

GoldenFloat

22

φ-семейство GF2…GF1024 + гибриды (GF+LNS, MXGF) (arXiv:2606.05017)

HistoricalVendor

10

IBM HFP, VAX (F/D/G/H), Cray, Microsoft MBF

PositUnumIII

8

Posit8…64, takum8…64 (Hunhold 2024)

IntegerFixed

8

INT4…INT128, Q-формат, BCD

MlLowPrecision

7

bfloat16, TF32, FP8 (E4M3/E5M2), FP6, FP4

Ieee754Binary

5

binary16/32/64/128/256

Theoretical

4

minifloat, Unum I/II, tapered FP

Lns

4

логарифмические LNS-8…64

CompressionTrick

4

block FP, shared-exponent, per-channel scale, stochastic rounding

Microscaling

3

MXFP8/6/4 (общая экспонента E8M0) (Rouhani 2023)

Ieee754Decimal

3

decimal32/64/128

ExtendedFloat

3

x87 FP80, double-double, quad-double

QuantTuned

2

NF4 (Dettmers 2023), AFP

Разрядность охватывает диапазон от 2 бит (балансная троичность GFTernary) до 1024 бит (GF1024 — крайняя ступень φ-лестницы). Каждая строка несёт не только s/e/m/bias, но и поле phi_distance — насколько разбиение формата близко к тому, что диктует золотое сечение через тождество φ² + φ⁻² = 3.

Важная оговорка про слово «golden». Это стандартный отраслевой термин — эталонное значение, с которым сравнивают результат (как эталонный метр в палате мер и весов). Его используют NVIDIA, Intel, все инженеры HDL и ML. Это не моё изобретение и не чьё-то ещё — каталог просто говорит на том же языке.

Статус-метки: главная честность каталога

Если бы я ставил одну вещь в центр всего проекта — это была бы дисциплина статус-меток. Каждый формат в каталоге несёт честный ярлык того, насколько он проверен:

Статус

Кол-во

Что означает

Verified

51

Проверен против эталона (стандарт или ml_dtypes)

Historical

12

Исторический формат (IBM, VAX, Cray…), для полноты

Experimental

11

Спека + частичная реализация, без полного покрытия

Open

9

Только спецификация, выведенная из правила; без RTL

Вот это — суть. И здесь проходит самая важная честная граница каталога: где правило e = round((N−1)/φ²) ещё является работающим железом, а где оно уже становится гипотезой. GF16 проверен вплоть до кремния (FPGA 35/35 тестов, 323 МГц на Artix-7, кремниевый якорь). Для ступеней GF48…GF256 написан RTL, но кремния под ними нет. А GF512 и GF1024 — это уже чистая экстраполяция правила: у них в SSOT прямо стоит пометка (extrapolation, no RTL), и я не делаю вид, что они проверены. Подробно эту лестницу статусов я разбираю ниже.

Эта честность стоит дороже, чем красивые цифры. В каталоге значение 0.1 в bfloat16 показано с ненулевой ошибкой — потому что 0.1 в bf16 не представимо точно. Прятать это означало бы испортить саму линейку.

Граница RTL: где правило перестаёт быть железом

Это самая честная часть статьи. φ-семейство построено на одном правиле: для ширины N бит число бит экспоненты e = round((N−1)/φ²), мантисса m = N − 1 − e, сдвиг bias = 2^(e−1) − 1. Правило красивое и применимо к любой ширине. Но «формат описан правилом» и «формат работает в железе» — это разные статусы реализации, и я не имею права их путать.

Вот лестница статусов реализации φ-ступеней — ровно так, как она есть в репозиториях сегодня:

Статус реализации

Ступени

Что реально есть

Проверено вплоть до кремния

GF16

RTL + FPGA 35/35 @ 323 МГц + кремниевый якорь gf16_v2_mul.v

RTL + бенчмарк (Verified)

GF8, GF12, GF32, GF64

файлы _add.v / _mul.v + измерения

RTL написан, кремния нет (Open / Exp)

GF6, GF10, GF14, GF20, GF24, GF48, GF96, GF128, GF256

_add.v / _mul.v существуют (сумматор GF256 ≈ 939 строк Verilog); тесты местами

Чистая экстраполяция, RTL НЕТ (Open)

GF512, GF1024

только спека; файлов gf512* / gf1024* в RTL нет

Главный честный парадокс здесь — GF1024. По метрике близости к φ это лучшая ступень лестницы (phi_distance ≈ 0.0006), и именно она наименее проверена: ни одной строки Verilog. В SSOT её use_case буквально записан как (extrapolation, no RTL). Красивая метрика не повышает статус реализации — и каталог это показывает, а не прячет.

И RTL, который есть, — не декорация. Умножитель GF256 в начале июня переписали после реального бага: произведение мантисс было на 2 бита у́же, чем нужно, и 1.0 × 1.0 давало 0.5. Это нашли, потому что под форматом есть железо, которое можно прогнать. Под GF512/GF1024 такого железа пока нет — поэтому они и помечены честно.

Уточнение по слову «статус»: это свойство не формата, а моей реализации. GF512 тривиально реализуем в железе с предсказуемыми характеристиками — метка просто говорит, что я этого пока не сделал и не прогнал. Тот же FP8 за полгода прошёл путь от спеки до кремния; метка фиксирует точку на этом пути, а не вечное свойство. И что детали за пределами разрядки реальны, видно по самому FP8: существуют два несовместимых E4M3 (OCP и IEEE-style) с разным кодированием NaN/inf, а первое open-source FP8-расширение SoftFloat в процессе верификации нашло и исправило ошибки в готовом векторном FP-блоке.

Якорь 0x47C0: одна точка проверки на всех

У каталога есть единая «реперная точка». Она вытекает из того же тождества: φ² + φ⁻² = 3 = L₂ (второе число Люка). Если посчитать dot4(1, 2, 3, 4) в формате GF16, бит-в-бит получается значение с отпечатком 0x47C0. Этот якорь проносится без изменений через все реализации — от JSON-векторов до RTL-декодеров на кремнии (проект Corona). Любое расхождение в этой одной точке означает, что где-то линейка сбита.

Это механическая проверка «одинаковости», а не доказательство превосходства. И тут важная оговорка, которую я держу жёстко: φ-семейство заслуживает место в каталоге широтой охвата и связностью тулчейна, а не тем, что каждая ступень бьёт конкурента. takum (Hunhold, 2024) — стоящий контрпример, и он не спрятан: он лежит в каталоге рядом со всеми.

Линейка, кластеры, якорь 0x47C0

Линейка, кластеры, якорь 0x47C0

Связь с IEEE P3109

Рабочая группа IEEE P3109 стандартизирует семейство 8-битных форматов для машинного обучения. В каталоге есть cross-walk — одностраничная карта, которая сопоставляет семейство P3109 binary8 (p1…p7) с индексами каталога. Это не заявление о соответствии стандарту — это справочник для разработчиков, который сама рабочая группа может проверить и поправить. Там, где есть расхождение, каталог уступает Lean-формализации FLoPS (arXiv:2602.15965).

Это сознательная позиция: входить не с требованием «примите нас», а с проверяемой информацией, которую можно сверить.

Что это даёт на практике

Самое прямое применение — арбитр при расхождении точности. Когда один и тот же расчёт даёт разные результаты на двух устройствах (классическая боль: PCC падает с 0.99 до 0.93 при другой блокировке редукции), бит-точный эталон формата отвечает на вопрос «чей результат корректен» механически, а не на глаз.

Второе применение — кодоген под новое железо. Из одной спеки выводятся декодеры на нужном языке, включая RTL. Цепочка SSOT → кодоген → RTL → кремний целиком механическая; CI-гейт rom_readback ловит любое расхождение между спекой и тем, что реально лежит в ПЗУ декодера на чипе.

Третье — общий словарь. Когда вы и ваш собеседник из другой команды называете один и тот же формат одинаково, с одинаковой разрядкой и одинаковым поведением на границах, исчезает целый класс споров «у нас не так».

Честные ограничения

Чтобы статья не превратилась в рекламу, перечислю прямо:

  • Проверка кремнием — пока только GF16. Для GF48…GF256 RTL написан, но не в кремнии; GF512 и GF1024 — чистая экстраполяция правила без RTL. Самая близкая к φ ступень (GF1024) — наименее проверенная.

  • Кремний Corona — это законченный дизайн (RTL + GDS + формальная верификация + cocotb), а не отлитый чип. Проверено в симуляции и формально; кремний впереди.

  • φ-семейство не заявлено как «лучше всех». Место в каталоге — за широту и связность, не за победу по каждой ступени. takum в каталоге как стоящий контрпример.

Каталог — это инструмент и дисциплина, а не финальное слово. Линейка хороша ровно настолько, насколько честны её насечки — поэтому я и показываю, где они сейчас сбиты.


Источники и материалы:

Аффилиация: Trinity S³AI (независимый исследовательский коллектив). ORCID: 0009-0008-4294-6159. Контакт: admin@t27.ai (асинхронно).

Автор: raoffonom

Источник