低精度数値形式の系譜 ─ FP16/BF16/FP8/INTとブロック浮動小数点
なぜAIはFP32より荒い数で速く回るのか。FP16・BF16・FP8・INT8・MXFPの指数仮数配分とダイナミックレンジ、量子化誤差、共有指数の損得を系統立てて掴めます。
- 1.浮動小数点は指数ビットがダイナミックレンジを、仮数ビットが相対精度を決め、FP16は精度寄り(E5M10)、BF16は範囲寄り(E8M7)で同じ16ビットを分け合う。
- 2.FP8はE4M3(精度寄り・推論や前向き計算)とE5M2(範囲寄り・勾配)を用途で使い分け、整数INT8はスケールとゼロ点で実数へ写す量子化を前提とする。
- 3.MXFPなどブロック浮動小数点は数十要素で指数を共有し、要素あたりのビットを削りつつブロック内ダイナミックレンジを確保する面積と精度の折衷である。
なぜビット幅を削るのか ─ 帯域・面積・精度の三すくみ
AIアクセラレータの律速は、演算器そのものよりデータをどれだけ速く供給できるかです。重みや活性化を半分のビット幅にすれば、メモリ帯域とキャッシュ占有が単純に半減し、同じシリコン面積により多くの乗算器を詰め込めます。乗算器の面積はビット幅のおよそ2乗で効くため、8ビット化はFP32比で乗算面積を大きく削れます。
ただし削れば表現できる数が粗くなる。どこを削るかが形式設計の核心で、浮動小数点なら「指数ビット(ダイナミックレンジ)」と「仮数ビット(相対精度)」のどちらを優先するか、整数なら「スケーリングで実数をどう写すか」という分岐になります。本稿はこの分岐を年代順に系統立てて追います。
浮動小数点値は「符号 × 仮数 × 2の指数乗」で表します。指数ビット数が**表せる値の範囲(最小から最大までの桁数)を決め、仮数ビット数がある値の近傍をどれだけ細かく刻めるか(相対誤差の上限)**を決めます。仮数 m ビットなら相対誤差はおおむね 2 の マイナス(m+1)乗 で頭打ちになり、これは絶対値の大小によらず一定です。ここが固定小数点や整数との決定的な違いです。
系統と年代 ─ FP32から低精度形式への分岐
低精度形式は一本道ではなく、用途ごとに枝分かれしてきました。年代と分岐を整理します。
- 基準(1985, IEEE 754): FP32(E8M23)とFP64(E11M52)。汎用計算の土台。指数8ビットで約10の正負38乗までの広い範囲を持つ。
- 半精度の標準化(2008, IEEE 754改訂): FP16(E5M10)。16ビットへ縮める際、仮数を10ビット残し精度を優先した。代償に指数が5ビットへ減り、表せる範囲が約 6万 までと狭い。
- 範囲優先の分岐(2018前後, Google Brain): BF16(E8M7)。FP32の指数8ビットをそのまま維持し、仮数だけを23から7へ削った。FP32と同じ範囲を持つため、勾配のように極端な大小をとる値でもオーバーフロー/アンダーフローしにくい。学習で主流化した。
- 8ビットの二系統(2022, NVIDIA/Arm/Intel共同提案): FP8。一つの8ビットに収めきれないので、精度寄りのE4M3と範囲寄りのE5M2の二形式を定義し、前向き計算(活性化・重み)と勾配で使い分ける。
- ブロック浮動小数点の標準化(2023, OCP MXフォーマット): MXFP8/MXFP6/MXFP4 など。要素を小さくしつつ、ブロック単位で**共有指数(スケール)**を持たせて範囲を回復する方式。
両者とも16ビットですが、配分が真逆です。FP16は仮数を厚くして近傍の刻みを細かくし、BF16は指数を厚くして扱える桁数を広げます。学習で勾配が極小値をとってもBF16なら表現でき、損失スケーリングなしでも安定しやすい。一方FP16は範囲が狭いため、学習では勾配を定数倍してから演算する損失スケーリングで対処するのが定石でした。
ダイナミックレンジと相対精度を並べる
各形式のビット配分が、範囲と精度にどう跳ね返るかを表で並べます。範囲はおおよその正規化数の絶対値上限、刻みは仮数由来の相対誤差の目安です。
| 形式 | ビット配分(符号/指数/仮数) | おおよその範囲(正の最大) | 相対精度(刻み) | 代表的な用途 |
|---|---|---|---|---|
| FP32 | 1/8/23 | 約3.4×10^38 | 約1.2×10^-7 | 基準計算・最終累算 |
| FP16 | 1/5/10 | 約6.5×10^4 | 約4.9×10^-4 | 推論・学習(範囲が狭い) |
| BF16 | 1/8/7 | 約3.4×10^38 | 約3.9×10^-3 | 学習(範囲重視) |
| FP8 E4M3 | 1/4/3 | 約448 | 約6.3×10^-2 | 前向き・推論(精度寄り) |
| FP8 E5M2 | 1/5/2 | 約5.7×10^4 | 約1.3×10^-1 | 勾配(範囲寄り) |
| INT8 | 整数(スケール別持ち) | スケール依存 | 1/スケール | 量子化推論 |
注目点は、指数ビットが同じならほぼ同じ範囲を持つことです。BF16とFP32は指数8で範囲が揃い、E5M2とFP16は指数5で範囲が近い。一方、仮数が薄いほど刻みは荒くなり、E4M3は相対誤差が数パーセント規模に達します。だからこそ累算はTensorコアの混合精度のようにFP32で行い、低精度は入力側に限定するのが原則になります。
量子化誤差 ─ 整数INT8の写像と外れ値問題
INT8は浮動小数点と発想が異なり、実数の範囲を**スケール(scale)とゼロ点(zero point)**で整数格子へ写します。基本式は次の通りです。
量子化: q = round(r / scale) + zero_point
逆量子化: r ≈ scale * (q - zero_point)
r: 実数, q: 整数(例 -128..127), scale: 1刻みの実数幅
scale = (rmax - rmin) / (qmax - qmin)
ここで誤差源は二つあります。一つは丸めによる量子化誤差で、最大で scale の半分。もう一つが**飽和(クリッピング)で、scale を広げて範囲を取ると刻みが粗くなり、狭めると外れ値が振り切れて潰れます。Transformer系では一部チャネルに巨大な外れ値(アウトライア)**が出るため、テンソル全体で1つのscaleを使う粗い量子化(per-tensor)では精度が崩れやすい。
対策は scale の粒度を細かくすることです。チャネルごとに別scaleを持つ per-channel、さらに細かく行・小ブロックごとに持つ手法へと進むと、外れ値の影響を局所化できます。粒度を上げるほど精度は戻りますが、scale を保持・適用するメタデータと演算が増え、ハードの実装コストと引き換えになります。対称量子化(zero_point を 0 固定)か非対称かの選択も、ReLU後のように片側に偏る分布では効きます。
ブロック浮動小数点 ─ 共有指数という折衷
FP8をさらに削ってFP4(仮数1〜2ビット)まで行くと、単独の浮動小数点では範囲も精度も足りません。そこで登場するのが**ブロック浮動小数点(block floating point)**で、MXFP(Microscaling)系がその標準形です。
考え方は、要素を数十個(典型的に32要素)のブロックにまとめ、ブロックで共有する**スケール(共有指数)**を1つ持たせる、というものです。各要素は小さな仮数だけを持ち、共有スケールでブロック全体を底上げします。
MXFP の構造(ブロック=32要素の例)
共有スケール X (例 8ビットの2の冪) ── ブロック全体に乗算
要素 e0, e1, ... e31 各々が低ビット要素(例 FP8/FP6/FP4)
実値 ≈ X * element[i]
→ 1要素あたりのビット = 要素ビット + (スケール8ビット / 32要素)
利点は、要素あたりの実効ビットを下げつつブロック内のダイナミックレンジを共有スケールで確保できること。スケール1本のコストを32要素で割れば、要素あたりの上乗せはわずかです。欠点は、ブロック内に1つでも大きな外れ値があると共有スケールがそれに引っ張られ、他の小さな要素の刻みが粗くなること。つまりブロック内の値が揃っているほど報われ、ばらつくと精度が落ちます。ブロックサイズはこの綱引きで、大きいほどメタデータは軽いが外れ値耐性は下がります。
「指数ビット=ダイナミックレンジ、仮数ビット=相対精度」「FP16(E5M10)は精度寄り・範囲狭い、BF16(E8M7)はFP32と同じ範囲で学習向き」「FP8はE4M3(精度寄り)とE5M2(範囲寄り)の二系統」「INT8はスケールとゼロ点で実数を写し、丸めと飽和が誤差源」「ブロック浮動小数点は共有指数で要素ビットを削りつつ範囲を確保する折衷」の5点を押さえましょう。
まとめ
- 低精度化の動機は帯域・キャッシュ占有・乗算器面積の削減で、削る対象は浮動小数点なら指数(範囲)と仮数(精度)の配分、整数なら量子化の写像に分かれる。
- 同じ16ビットでもFP16は精度寄り(範囲が狭く損失スケーリングが要る)、BF16は範囲寄り(FP32と同じ範囲で学習に強い)と鏡像の関係にある。
- FP8はE4M3とE5M2の二形式を前向き計算と勾配で使い分け、INT8はスケールとゼロ点による量子化で、外れ値対策として粒度を細かくする。
- **ブロック浮動小数点(MXFP)**は数十要素で共有指数を持ち、要素ビットを削りつつブロック内の範囲を確保する折衷で、外れ値が少ないほど報われる。
形式選びは「必要な範囲と精度を最小ビットで満たす」最適化です。これらが実際にどう積和へ流れ込むかはTensorコアと行列演算を、誤りに対する別軸の冗長設計はECCとエラー訂正も合わせてどうぞ。
CPU/メモリ/ディスク Article
低精度数値形式の系譜 ─ FP16/BF16/FP8/INTとブロック浮動小数点を実務で読む
TL;DRは入口です。実際に選ぶ・使う段階では、何を解決するか、何と比較するか、導入後にどこで詰まるかまで見る必要があります。
解決すること
低精度演算
比較で見る軸
難易度: advanced / カテゴリ: CPU/メモリ/ディスク / タグ数: 5
導入後に効く点
FP8はE4M3(精度寄り・推論や前向き計算)とE5M2(範囲寄り・勾配)を用途で使い分け、整数INT8はスケールとゼロ点で実数へ写す量子化を前提とする。
先に潰すリスク
用語だけ覚えても、設計・実装・運用でどこに効くかを確認しないと判断を誤る。
- 難易度
- advanced
- カテゴリ
- CPU/メモリ/ディスク
- タグ数
- 5
判断チェックリスト
- 自社の用途が「低精度演算 / 浮動小数点」に近いか確認する。
- 強みである「浮動小数点は指数ビットがダイナミックレンジを、仮数ビットが相対精度を決め、FP16は精度寄り(E5M10)、BF16は範囲寄り(E8M7)で同じ16ビットを分け合う。」が本当に評価軸になるか確認する。
- 注意点の「用語だけ覚えても、設計・実装・運用でどこに効くかを確認しないと判断を誤る。」を運用で吸収できるか確認する。
- 公開値や仕様値は、対象プラン・対象機種・対象リージョンまで確認する。
- 既存システム、ID、ネットワーク、監視、バックアップとの接続方法を先に洗い出す。
- 小さく試してから、本番移行、権限設計、障害時手順、コスト監視を決める。