Finite FP16 MX blocks become NaNs on the default PyTorch path
評価
- 難易度
- 4/5
- 見積もり時間
- 3〜5日
- 初心者へのやさしさ
- 48/100
- issue の種類
- バグ
- 明瞭さ
- 明確に書かれている
- 活発さ
- 活発
調査の方向性
Start with mx/mx_ops.py at the reported scale calculation around line 285, then inspect the zero guard around line 78. Run the provided reproduction on CPU and compare the six formats and the linear call with the expected finite outputs. Done means zero blocks stay zero and the small E5M2 block and public linear call return finite expected results; the report says no correction was tested.
索引モデルが issue の本文から書いたものです。
説明
Finite FP16 blocks become NaNs during MX quantization with custom_cuda=False. This includes zero blocks and a public linear call that should return zero.
Tested at microsoft/microxcaling commit 7bc41952de394f5cc5e782baf132e7c7542eb4e4 (mx==1.1.0). Both fresh environments used Python 3.12.3 and NumPy 1.26.4 on x86_64 Linux. The failure reproduced with CPU PyTorch 2.2.0+cpu and 2.4.0+cpu.
Reproduction
Run these commands in Bash with Python 3.12.3. The example is CC0.
git clone https://github.com/microsoft/microxcaling.git microxcaling
cd microxcaling
git checkout --detach 7bc41952de394f5cc5e782baf132e7c7542eb4e4
python3.12 -m venv .venv
.venv/bin/python -m pip install torch==2.4.0 --index-url https://download.pytorch.org/whl/cpu
.venv/bin/python -m pip install numpy==1.26.4 packaging ninja==1.13.2 hatchling==1.32.4 hatch-vcs==0.5.0 editables
MAX_JOBS=1 .venv/bin/python -m pip install --no-build-isolation --no-deps -e .
OMP_NUM_THREADS=1 MKL_NUM_THREADS=1 .venv/bin/python - <<'PY'
import torch
from mx import linear
from mx.mx_ops import quantize_mx_op
from mx.specs import MxSpecs
torch.set_num_threads(1)
specs = MxSpecs()
specs.update(scale_bits=8, block_size=32, custom_cuda=False)
formats = (
"fp8_e5m2", "fp8_e4m3", "fp6_e3m2",
"fp6_e2m3", "fp4_e2m1", "int8",
)
for fmt in formats:
x = torch.zeros(32, dtype=torch.float16)
y = quantize_mx_op(x, specs, fmt, axes=-1, round="even")
print(fmt, "zero NaNs:", y.isnan().sum().item())
x = torch.zeros(32, dtype=torch.float16)
x[0] = 2**-10
y = quantize_mx_op(x, specs, "fp8_e5m2", axes=-1, round="even")
print("E5M2 small:", y[:2].tolist())
specs.update(
a_elem_format="fp8_e5m2", w_elem_format="fp8_e5m2",
quantize_backprop=False,
)
output = linear(
torch.zeros((1, 32), dtype=torch.float16),
torch.ones((1, 32), dtype=torch.float16),
mx_specs=specs,
)
print("linear:", output.item())
PY
For the other tested Torch version, use a fresh venv and substitute torch==2.2.0 in the install command. The no-dependency editable install omits unused torchvision and torchaudio, whose dependency mismatch is already reported in issue 31.
Expected and observed
The README documents native FP16 computation and CPU as the numeric reference. PR 28 added native FP16 support.
All-zero blocks should remain zero. For the small E5M2 block, the implemented scale algorithm selects X=2^-25 (E8M0 byte 0x66). The nonzero element is 2^15 (E5M2 code 0x78), so the decoded result is exactly 2^-10. Zero elements remain zero. OCP MX v1.0 §5.1 and Tables 2 and 7 define these finite encodings and products. The scale need not fit the FP16 container. An all-zero block does not require a unique scale.
These encodings are derived expectations for this library's maximum-based scale algorithm. The API returns dequantized tensors, and MX §6.3 permits other scale-selection algorithms.
| Case | Expected | Observed on both Torch versions |
|---|---|---|
| Zero block, each of the six formats | 32 zeros, no NaNs | 32 NaNs |
E5M2 block with 2^-10 and 31 zeros |
Identical finite block | 32 NaNs, beginning [nan, nan] |
FP16 zero input and unit weights in linear |
0.0 |
nan |
Source and scope
mx_ops.py:285 computes 2**shared_exp in FP16. The exact 2^-25 scale rounds to zero before division. Zero blocks also lose the FP32 zero guard at mx_ops.py:78 and underflow the clamped scale. Scale and normalization intermediates need a type that represents these values. No correction was tested.
Zero blocks were checked in all six formats with even, nearest, floor and both FP32-flush settings. The small input is an exact power of two. Wider FP32/BF16 inputs and the FP16 2^-9 threshold control passed. The original C++ CPU numeric code returned the expected values through a CPU-only build adapter. The adapter preserved the numeric code and changed only build plumbing. The stock CUDA extension and GPU execution were not tested. These cases use finite inputs and forward computations.
Found by ChipLab's AI verification agents and independently reproduced.
ChipLab ref: CLAB-2026-623
- 主要言語
- Python
- スター
- 365
- フォーク
- 54
- PR マージ指標
- 30日以内にマージされた PR はありません
環境構築
- Dockerfile・Docker Compose ファイルなし
- プルリクエストのテンプレートなし
- コントリビューションガイドを読む
はじめの一歩
- issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
- 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
- リポジトリをフォークし、ブランチを切って変更します。
- issue 番号を参照したプルリクエストを送ります。
microsoft/microxcaling のほかの issue
-
難易度 2/5 1〜3時間 初心者へのやさしさ 85/100
microsoft/microxcaling#49 ·
-
難易度 2/5 1〜3時間 初心者へのやさしさ 74/100
microsoft/microxcaling#48 ·
-
難易度 5/5 1週間以上 初心者へのやさしさ 20/100
microsoft/microxcaling#43 ·
-
難易度 2/5 1〜3時間 初心者へのやさしさ 35/100
microsoft/microxcaling#42 ·
-
難易度 2/5 1〜3時間 初心者へのやさしさ 45/100
microsoft/microxcaling#36 ·
microsoft/microxcaling の issue をすべて見る
似ている issue
-
Project submission:オープン
難易度 1/5 1時間未満 初心者へのやさしさ 72/100
slavakurilyak/awesome-ai-agents#845 ·
メンテナーはふだん 1 日以内に返信
-
tests: pin that the atomic writers in utils/paths.py stage the temporary file in the target's directory対応中かも このイシューにリンクされたプルリクエストがオープン中、またはマージ済みです。 オープンdifficulty:2 enhancement good first issue
難易度 1/5 1〜3時間 初心者へのやさしさ 92/100
MakazhanAlpamys/Soup#2178 ·
メンテナーはふだん 1 日以内に返信
-
[BUG] dcg.waggr permutation p-values are folded twice, so near-zero scores get the smallest p-valuesオープン
難易度 2/5 1〜3時間 初心者へのやさしさ 75/100
scverse/rapids-singlecell#854 ·
メンテナーはふだん 1 日以内に返信
-
Slang input: int8_t4_packed and uint8_t4_packed are copied into CrossGL対応中かも @ninglinLiu が今日担当しました。 オープンarea:frontend backend:slang bug direction:input
難易度 2/5 1〜3時間 初心者へのやさしさ 70/100
メンテナーはふだん 1 日以内に返信
-
難易度 2/5 1〜3時間 初心者へのやさしさ 85/100
メンテナーはふだん 13 日以内に返信