Comments 4
Хотелось бы уточнить - обычный float/double на x86 - это GF32/GF64 в вашей статье или что то другое?
Ваши форматы - это лишь чуть-чуть измененное соотношение битности мантиссы/экспоненты. При чем никаких измерений о том, чем оно лучше и для каких задач нет.
Каталог форматов - это одна табличка. Это трактат на 1-2 страницы. Делать из этого несколько статей - моветон.
Алгоритмы вычислений с числами с плавающей точкой не имеют каких-то особых случаев в зависимости от битности (кроме возможно крайних случаев 1 битности, но это тривиальный неинтересный случай). Ну им безразницы складывать ли 7 битные мантиссы, или 9 битные. В железе просто добавляются полу-сумматоры какие-нибудь нужное количество раз. Схемы обобщаются на n бит тривиально.
Как-то верифицировать эти вычисления для чуть других размеров полей - бессмысленная и бесполезная работа. Имеет смысл может быть проверять вашу реализацию с точки зрения, что вы там не набаговали при реализации, но это тупо отладка, и никакое не свойство формата.
Вы бы еще придумали свой "брильянотвый int" размером 37 бит. Ведь такого нигде нет. Новое у уникальное. Нигде не опубликованное. А потом в поте лица верифицировали бы, что такие числа можно складывать и умножать.
Что касается "закона" - это карго культ. Никакой пользы не несет, выбраны ли размеры мантиссы и экспоненты по кокнретному закону, или пальцем в небо, если этот закон тоже выбран пальцем в небо.
Вся эта движуха просто пахнет курсовой студента, которому нужна актуальность и новизна и выдумывается что-то бесполезное, пишется раздутое описание, а потом усиленно не замечается слон в комнате - ведь смысла никакого в этом нет (кроме того, что студенту нужен зачет, но вслух это говорить нельзя).
Спасибо за разбор — отвечу по пунктам, со ссылками на первоисточники, а не на собственные слова. Часть критики справедлива, и я это отмечу прямо. Но центральный технический тезис — «схемы обобщаются тривиально, а складываемость безразлична к содержимому» — расходится с тем, что реально происходит в индустрии прямо сейчас. Конкретика ниже.
1. «Им безразлично, складывать 7-битные мантиссы или 9-битные. Схемы обобщаются на n бит тривиально».
Для сложения двух нормальных чисел — почти да. Но ровно там, где «тривиально», и сидят баги. И это не моё мнение:
Округление субнормалей в умножителе зависит от ширины. Построчный разбор типовой реализации FPU на Verilog прямо говорит: «эти определения старшей и младшей части произведения неправильны для субнормальных чисел; для них нужно добавить хотя бы один ведущий ноль», и далее — «сколько ведущих бит мы добавляем и сколько отрезаем, зависит от значения экспоненты» (Building an FPU in Verilog: Rounding Subnormal Numbers). То есть формула, верная для нормального произведения, на субнормалях даёт неверный результат, и поправка — функция от exponent и числа значащих бит, а значит и от ширины формата.
Поддержку субнормалей в железе часто вообще выкидывают ради площади. Официальная документация AMD на DSP58: «когда DSP58 обнаруживает субнормальный операнд, он трактует его как ноль с сохранением знака… субнормальный выход flush-ится в ноль» (AMD Versal DSP Engine docs). У NVIDIA в fast-режиме субнормали тоже flush-ятся в ноль, в IEEE-режиме — нет (NVIDIA, Floating Point on NVIDIA GPU). То есть «формат тот же, ширина та же» — а поведение на краю разное в зависимости от того, реализованы субнормали или flush-to-zero. Где именно срабатывает FTZ-логика (до или после округления) — тоже расходится между реализациями (Stack Overflow, FLT_HAS_SUBNORM).
Так что «обобщается тривиально» верно для учебного нормального случая и ломается на краях. А края — это ровно то, что меряет каталог.
2. «Им безразлично, что складывать».
Три контрпримера прямо из продакшена, не из моей головы.
Один формат — три разные конвенции округления. Для блочного масштаба E8M0 в MX: PyTorch округляет RNE, спецификация MX требует round-toward-zero, а CUDA 12.8 — round-toward-zero либо round-toward-+inf. Это дословно зафиксировано в трекере PyTorch: «rounding: RNE… note that this does not match the rounding to e8m0 in the MX spec (round towards zero), or the rounding to e8m0 in CUDA 12.8 (round towards zero or round towards positive infinity)» (pytorch/pytorch#146414). Один и тот же формат, три несовпадающих результата на трёх стеках.
Два несовместимых FP8 E4M3. У одного переполнение при кодировании насыщается до 448.0 (tt-metal, AMD), у другого уходит в NaN (исходный NVIDIA float8_e4m3fn, JAX). Стандарт OCP MX явно разрешает оба режима — «narrowing conversions support both saturate and non-saturate modes» — и относит к implementation-defined ещё и конверсию NaN в FP6/FP4/INT8, и даже кодирование −2.0 в INT8 (FPRox: OCP MX Scaling Formats). Биты те же, ширина та же, поведение на границе диаметрально разное.
И это не косметика — это рушит обучение. Kempner Institute (Harvard) обучил почти тысячу языковых моделей и показал, что MXFP8 E4M3 систематически вызывает нестабильность: значение клампится в «overflow region», если его модуль больше 87.5 % абсолютного максимума в 32-элементном блоке; для log-normal-распределённых весов layer-norm это значит, что все 32 веса в блоке схлопываются в одно число, и градиент начинает расти неконтролируемо перед взрывом лосса (Kempner Institute, 2025).
Если «безразлично, что складывать» — объясните, почему один тензор на двух стеках даёт 448.0 против NaN, почему один блок округляется тремя способами, и почему Harvard’у пришлось обучить ~1000 моделей, чтобы поймать поведение края формата. Каталог фиксирует именно такие развилки: не «новый формат», а какое поведение у какой реализации на краю, с битовым якорем 0x47C0 для сверки.
3. «Верифицировать вычисления для других размеров — бессмысленно. Это тупо отладка, а не свойство формата».
Здесь вы фактически сформулировали мой же тезис, и я с ним согласен. Я нигде не утверждаю, что «складываемость» — свойство формата. Метка Verified в каталоге означает буквально «реализация сверена с эталоном бит-в-бит», то есть да — это про отладку и воспроизводимость, а не про абстрактную математику. Ценность не в том, что «числа можно складывать» (можно, спасибо), а в том, что под меткой Verified стоит прогоняемый тест, а под Open — честно стоит «только спека, RTL нет». Каталог честен ровно в том, что не выдаёт отладочную проверку за открытие. Распределение статусов так и записано: из 83 форматов Verified — меньшинство, остальное помечено Historical / Experimental / Open.
4. «Закон выбора битов — карго-культ. Нет разницы, по закону или пальцем в небо».
Сильное замечание, отвечу прямо: я НЕ утверждаю превосходства φ-разбиения. У φ-семейства в каталоге нет метрики «лучше всех» — takum Хунхольда лежит там же как контрпример, не спрятан. Более того, литература прямо показывает, что универсально лучшего формата нет: в той же работе по takum posit слегка выигрывает на 8 и 16 битах, takum достигает паритета на 32 и обходит дальше, а по целочисленному представлению IEEE 754 обходит posit (Hunhold, arXiv:2412.20273). Выбор битов — это инженерный trade-off под диапазон и распределение, а не превосходство и не магия.
Единственное операционное отличие замкнутого правила от ручной таблицы — воспроизводимость кодогена: одно правило e = round((N−1)/φ²) порождает всю лестницу от 2 до 1024 бит без сшивки «ручной низ + формула для верха». Это не «точнее», это «однороднее по происхождению, поэтому проще механически генерировать и проверять декодеры». И тут уместно вспомнить: сам IEEE 754 даёт формулу ширины экспоненты w = round(4·log₂k) − 13 только как ненормативную заметку, и она не работает для 16 и 32 бит — их разбиение задано вручную (IEEE 754 §3.6, разбор на Stack Overflow). Так что «формула против ручной таблицы» — это ровно тот компромисс, который уже сделал и сам стандарт; я просто провёл одно правило через всю лестницу и пометил, где оно проверено кремнием, а где нет.
5. «Каталог — это одна табличка, трактат на 1-2 страницы. Делать из этого несколько статей — моветон».
Частично соглашусь: сам перечень — это таблица. Но статья не про таблицу. Она про то, что из одного файла-источника механически генерируются декодеры на Markdown/JSON/Python/Rust/C/RTL, и CI-гейт ловит расхождение спеки с тем, что реально лежит в ПЗУ декодера на кремнии. Это исполняемая спецификация-арбитр, а не описание. Код открыт и проверяем: Rust-ядро кодека GF16 — ffi/src/lib.rs, сгенерированный каталог — gen/numeric/formats_catalog.rs. Если две статьи — перебор, скажите, какую конкретно часть схлопнуть; я не держусь за объём.
6. «Брильянтовый int на 37 бит» и «пахнет курсовой студента».
Принято как удар, отвечу делом, а не обидой. Разница между «придумал формат и верифицировал, что числа складываются» и тем, что есть, — вот в чём: баг в умножителе GF256 (1.0 × 1.0 давало 0.5, потому что произведение мантисс выходило на 2 бита уже положенного) был найден и исправлен именно потому, что под форматом лежит RTL, который гоняется на тестах. Курсовая обычно заканчивается там, где у меня началась отладка железа. И «слон в комнате», которого я якобы не замечаю, в статье назван прямым текстом в разделе ограничений: кремнием проверен только GF16 (FPGA, тестбенч 35/35, 323 МГц на Artix-7); GF512/GF1024 — экстраполяция без единой строки Verilog; φ-семейство не заявлено как «лучше всех». Я этого слона не прячу — он стоит в отдельном разделе с заголовком «Ограничения».
Что из конкретики кажется лишним — уберу по пунктам, без обид. За критику спасибо: она по делу там, где про объём и про отсутствие сравнительных бенчмарков по всей лестнице — их и правда нет, измерен end-to-end только GF16, остальное честно помечено статусами.
Каталог из 83 форматов с плавающей точкой, который сам себя проверяет