[BUG] MSE histogram calibration: wrong amax for INT, TypeError for FP8 (args passed in the bias slot)

オープン 初心者向け
#3,261 コメント 0 件 リアクション 0 件 担当者 0 名 GitHub で見る

メンテナーはふだん 1 日以内に返信

まだ誰も着手していません。

評価

難易度
2/5
見積もり時間
1〜3時間
初心者へのやさしさ
82/100
issue の種類
バグ
明瞭さ
明確に書かれている
活発さ
活発
技術スタック
python, pytorch

調査の方向性

modelopt/torch/quantization/calib/histogram.pyから始め、fake_tensor_quantとscaled_e4m3のシグネチャとあわせて_compute_amax_mseを調べてください。issueにあるINT8とFP8のCPU例を再現し、その後、両方の形式について回帰テストを追加してください。両方が例外を発生させず妥当なamax値を返し、共有MSEキャリブレーション経路を通した場合も同様であれば完了です。

索引モデルが issue の本文から書いたものです。

説明

Describe the bug

HistogramCalibrator.compute_amax("mse") returns an amax that is far too small for INT formats. For FP8 (E4M3) it raises a TypeError. calibrate_weights(method="mse") goes through the same code, so it has the same problem.

The cause is in _compute_amax_mse in modelopt/torch/quantization/calib/histogram.py:

quant_centers = fake_tensor_quant(centers, amax, num_bits, unsigned)
...
quant_centers = scaled_e4m3(centers, amax, num_bits[0], num_bits[1])

Both functions now take bias as their third argument (fake_tensor_quant(inputs, amax, bias=None, num_bits=8, unsigned=False, ...), scaled_e4m3(inputs, amax, bias=None, E=4, M=3, ...)).

  • INT path: the call passes bias=8 and num_bits=False, so every candidate amax gives the same constant output and the same MSE. argmin then returns the first candidate, centers[start_bin].
  • FP8 path: M is missing, so the call raises.

Steps to reproduce

Main at 86bd9b78425a23a45b329c7c9b86ea772d7a9e77, CPU.

import torch
from modelopt.torch.quantization import calib

torch.manual_seed(0)
x = torch.randn(100_000)
print("max|x|:", x.abs().max().item())

for num_bits in (8, (4, 3)):
    cal = calib.HistogramCalibrator(num_bits, None, False, num_bins=2048)
    cal.collect(x)
    try:
        print(num_bits, "mse amax:", cal.compute_amax("mse").item())
    except Exception as e:
        print(num_bits, type(e).__name__, e)

Actual:

max|x|: 4.562695503234863
8 mse amax: 0.28628242015838623
(4, 3) TypeError ScaledE4M3Function.forward() missing 1 required positional argument: 'M'

Expected: an amax a bit below max|x| for both formats. With the arguments passed correctly the same script prints 4.0603 (INT8) and 4.3811 (FP8).

With CUDA available the histogram moves to the GPU and the quantizers go through the CUDA extension. The same script on B300 prints 4.5616 for INT8 (the amax lands at max|x|, not at the MSE optimum 4.0603) and the same TypeError for FP8.

Same effect through the public API on CPU: calibrate_weights(model, method="mse", perchannel=True) on an INT8 per-channel Linear(256, 4) sets every channel's amax to 0.0039 while max|w| is about 0.0625. The relative weight error after quantization is 0.908. With the fix it is 0.0039.

The existing TestMSECalibrator tests still pass on main. They only check that amax is closer to the bulk value than to the outlier, and the first candidate bin also satisfies that.

Proposed fix

Pass None for bias in both calls, plus a Gaussian regression test for INT8 and FP8.

Could a maintainer confirm this is a bug and not already fixed internally? I have the fix and tests ready and can open a PR after your reply.

主要言語
Python
スター
5.5k
フォーク
800
平均マージ
3日 6時間
マージ済み PR(30日)
267

環境構築

はじめの一歩

  1. issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
  2. 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
  3. リポジトリをフォークし、ブランチを切って変更します。
  4. issue 番号を参照したプルリクエストを送ります。

NVIDIA/Model-Optimizer のほかの issue

NVIDIA/Model-Optimizer の issue をすべて見る

似ている issue

Python の issue をもっと見る

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。