
2026/04/19 2:21
4 ビット浮動小数点形式 FP4
RSS: https://news.ycombinator.com/rss
要約▶
Japanese Translation:
概要:
ニューラルネットワークは、大規模な AI モデルのメモリ使用量を最適化するために FP8 および FP4 のような超低精度フォーマットを採用する傾向が高まっています。このトレンドは C 言語と Python ライブラングの双方によって支えられています。Python の
float は一般的に 64 ビットの二重精度を指しますが、専門的な縮小精度フォーマットが台頭しています。現在最も重要な進展は、1 つのビットを指数部、1 つのビットをマンティス部に用いる 4 ビット浮動小数点数(FP4)の E2M1 サブセットへの採用であり、これは計算タスクに適した非一様値分布を利用することで、従来の一様間隔配置や極端なケース(E3M0 の対数スケールまたは E0M3 の線形スケールなど)とは異なり、限られたメモリに多くのパラメータを圧縮して格納することを可能にします。符号付き 4 ビット数の場合、最初のビットが符号を表し、その後の構成によって値は約 -6 から +6 まで、0.5 刻みで表現でき、指数部がゼロのときに零および小数部分を特別に扱います。Python のpychopライブラリなどのツールが現在これら E2M1 フォーマットを実装していますが、分野は NF4 とような将来のフォーマットへ進化しており、それらは大規模言語モデルに見られる特定の重みの分布にさらに適切に合わせて設計されており、モデルがより複雑になるにつれて計算効率を維持しながら精度も過度に損なわずに行えます。本文
古くは、浮動小数点数は 32 ビットで格納されていましたが、やがて標準規格として 64 ビットへと移行しました。C プログラミング言語は古い慣習を受け継ぎ、
float で 32 ビットの浮動小数点数を指し、double ではそのビット数が倍である(64 ビット)ものを指しています。一方、Python は最も一般的な浮動小数点形式である C の double に相当するものを単に float と呼んでいます。
プログラマーたちは、32 ビットの float から 64 ビットの float への移行に感謝していました。精度が高くなることは害がなく、さらに多くの場合、32 ビットから 64 ビットへの変更によって数値的の問題が解消されます(ただしすべてではありません。私がこれまで多数指摘してきたことです)。
しかし、ニューラルネットワークは画期的な変化をもたらしました。それは、より少ない精度の浮動小数点数に対する需要を生み出したのです。これらのネットワークには膨大な数のパラメータが存在するため、パラメータの精度を高めることよりも、メモリ内により多くのパラメータを収めることが重要です。その結果、開発者たちは二倍精度(64 ビット)の代わりに、半分精度(16 ビット)、あるいはそれ以下の FP8(8 ビット)や FP4(4 ビット)のような形式を望みました。本稿では 4 ビットの浮動小数点数について考察します。
それほど高い精度が必要がないのに、なぜわざわざ浮動小数点数を使う必要があるのでしょうか?整数を使えばよいのではないか。例えば、4 ビットを用いれば 0 から 15 までの整数を表すことができます。さらにバイアスを導入して、各値から 7 を引くことで、その 4 ビットが -7 から 8 までを表すようにすることも可能です。しかしながら、より広いダイナミックレンジを持つことは有用であることが判明しました。
FP4 フォーマットの符号付き 4 ビット浮動小数点数では、最初のビットを符号用として使用します。残りの 3 ビットについてはどう扱うべきかという問題が生じます。表記法「ExMm」は、指数部に x ビット、仮数部(マンティッサ)に m ビットを持つ形式を指します。符号付き 4 ビット数の文脈では x + y = 3 となりますが、他の文脈ではその合計はさらに大きくなる場合もあります。例えば、8 ビットの符号付き浮動小数点数の場合、x + y = 7 となります。
符号付き 4 ビット浮動小数点数では、以下の 4 つのパターンが可能です:E3M0、E2M1、E1M2、および E0M3。これらはいずれもどこかで使用されていますが、その中で最も一般的であり、Nvidia のハードウェアでもサポートされているのは E2M1 です。
符号ビット s、指数 e、そして仮数 m を持つ数は、以下の式によって値を持ちます: (−1)^s × 2^(e−b) × (1 + m/2) ここで b はバイアスを表します。バイアスの目的は、e に符号を使用せずに正も負も負の指数を表すようにすることにあります。例えば、b = 1 とし、e が 1、2、3 のいずれであっても、2^(e−b) はそれぞれ 1、2、4 を表します。
バイアスは可能となる数の範囲に影響を与えますが、それらの相対的な間隔には影響しません。どんなバイアス値 b でも、E3M0 フォーマットは指数のみを使用し仮数は使用せず、したがってその可能な値は対数スケール上で一様に分布しています。一方、E0M3 フォーマットは仮数のみを使用するため、その値は線形スケール上で一様に分布します。E1M2 および E2M1 のフォーマットについては、対数スケールも線形スケールも両方において間隔のばらつきがあります。
上記の変換式(s, e, m)を実数に変換することに関する例外として、e = 0 の場合が挙げられます。この場合は、m = 0 が 0 を、m = 1 が ½ を表します。
値の表
FP4 の数全体で 16 つしか存在しないため、それら全てをリストアップすることが可能です。以下に E2M1 フォーマット用の表を示します。
| Bits | s | exp | m | Value |
|---|---|---|---|---|
| 0000 | 0 | 00 | 0 | +0 |
| 0001 | 0 | 00 | 1 | +0.5 |
| 0010 | 0 | 01 | 0 | +1 |
| 0011 | 0 | 01 | 1 | +1.5 |
| 0100 | 0 | 10 | 0 | +2 |
| 0101 | 0 | 10 | 1 | +3 |
| 0110 | 0 | 11 | 0 | +4 |
| 0111 | 0 | 11 | 1 | +6 |
| 1000 | 1 | 00 | 0 | -0 |
| 1001 | 1 | 00 | 1 | -0.5 |
| 1010 | 1 | 01 | 0 | -1 |
| 1011 | 1 | 01 | 1 | -1.5 |
| 1100 | 1 | 10 | 0 | -2 |
| 1101 | 1 | 10 | 1 | -3 |
| 1110 | 1 | 11 | 0 | -4 |
| 1111 | 1 | 11 | 1 | -6 |
この極めて小さな浮動小数点形式でありながら、+0 と −0 のふたつのゼロが存在することに留意してください。これは完全な精度を持つ浮動小数点数と同じようにです。その点については改めて触れます。
PyChop ライブラリ
Python ライブラリ
pychop は、多様な低精度浮動小数点形式をシミュレートします。上記の表を作成するために pychop を使用した代码如下です:
import pychop # Pychop からフォーマットのメタデータを取得する。 spec = pychop.MX_FORMATS["mxfp4_e2m1"] assert (spec.exp_bits, spec.sig_bits) == (2, 1) def e2m1_value(s: int, e: int, m: int) -> float: sign = -1.0 if s else 1.0 # 不準数/ゼロ if e == 0: return sign * (m / 2.0) # 正規化された数値 return sign * (2.0 ** (e - 1)) * (1.0 + m / 2.0) def display_value(bits: int, x: float) -> str: if bits == 0b0000: return "+0" if bits == 0b1000: return "-0" return f"{x:+g}" rows = [] for bits in range(16): s = (bits >> 3) & 0b1 e = (bits >> 1) & 0b11 m = bits & 0b1 x = e2m1_value(s, e, m) rows.append( { "Bits": f"{bits:04b}", "s": s, "exp_bits": f"{e:02b}", "m": m, "Value": display_value(bits, x), } ) # テーブルを整形して出力する。 header = f"{'Bits':<4} {'s':>1} {'exp':>3} {'m':>1} {'Value':>6}" print(header) print("-" * len(header)) for row in rows: print( f"{row['Bits']:<4} " f"{row['s']:>1} " f"{row['exp_bits']:>3} " f"{row['m']:>1} " f"{row['Value']:>6}" )
その他のフォーマット
FP4 のみが 4 ビット浮動小数点形式の唯一のものではありません。実際に使用されているフォーマットの数は驚くほど多いです。次回の記事で、別のフォーマットについても取り扱う予定です。
追記: 次の記事では、LLM の重みの分布に最もよく一致する表現可能な数値を持つフォーマットである NF4 について議論します。