Skip to content

Commit 5a691cb

Browse files
authored
Improvements to Gemma4 quant functions (#20768)
Differential Revision: D110919317 Pull Request resolved: #20768
1 parent f8c8334 commit 5a691cb

3 files changed

Lines changed: 36 additions & 13 deletions

File tree

backends/cuda/TARGETS

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,20 @@ load("@fbsource//xplat/executorch/build:runtime_wrapper.bzl", "runtime")
22

33
oncall("executorch")
44

5+
runtime.python_library(
6+
name = "int4_dispatch",
7+
srcs = [
8+
"int4_dispatch.py",
9+
],
10+
visibility = [
11+
"//executorch/...",
12+
],
13+
deps = [
14+
"//caffe2:torch",
15+
"//pytorch/ao:torchao",
16+
],
17+
)
18+
519
runtime.python_library(
620
name = "cuda_passes",
721
srcs = [

examples/models/gemma4_31b/quant/quantize.py

Lines changed: 21 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@
77
"""Quantize weights to torchao tensor subclasses.
88
99
``quantize_weight`` quantizes a single tensor given a ``QuantConfig``,
10-
returning an ``Int4Tensor`` (4-bit) or ``IntxUnpackedToInt8Tensor`` (8-bit).
10+
returning an ``Int4Tensor`` (4-bit) or ``IntxUnpackedToInt8Tensor`` (6- or
11+
8-bit).
1112
1213
``quantize_model`` walks a model's parameters, applies a ``QuantRecipe``,
1314
and returns a single state dict containing both quantized subclass tensors
@@ -152,11 +153,14 @@ def _to_intx_tensor(
152153
weight: torch.Tensor,
153154
config: QuantConfig,
154155
) -> torch.Tensor:
155-
"""Quantize 8-bit and wrap in IntxUnpackedToInt8Tensor.
156+
"""Quantize to 6- or 8-bit and wrap in IntxUnpackedToInt8Tensor.
156157
157158
Quantizes in float32 for numerical precision, then constructs the
158159
subclass directly. We avoid ``from_hp`` because it quantizes in the
159160
input dtype (bf16), which loses precision for small-magnitude weights.
161+
162+
Sub-byte data (e.g. 6-bit) is still stored unpacked in an int8 container;
163+
``target_dtype`` records the true bit width for the export/runtime path.
160164
"""
161165
from torchao.quantization import IntxUnpackedToInt8Tensor
162166
from torchao.quantization.quant_primitives import (
@@ -165,19 +169,23 @@ def _to_intx_tensor(
165169
quantize_affine,
166170
)
167171

172+
qmin = -(1 << (config.bits - 1))
173+
qmax = (1 << (config.bits - 1)) - 1
174+
target_dtype = getattr(torch, f"int{config.bits}")
175+
168176
if config.method == "hqq":
169177
if not config.symmetric:
170178
raise ValueError(
171-
"8-bit HQQ only supports symmetric quantization "
172-
"(HQQ_SCALE_ONLY). Use method='min_max' for asymmetric 8-bit."
179+
"intx HQQ only supports symmetric quantization "
180+
"(HQQ_SCALE_ONLY). Use method='min_max' for asymmetric intx."
173181
)
174182
from torchao.quantization.quant_primitives import (
175183
_choose_qparams_and_quantize_scale_only_hqq,
176184
)
177185

178186
w2d = weight.float().reshape(-1, weight.shape[-1])
179187
qdata, scale = _choose_qparams_and_quantize_scale_only_hqq(
180-
w2d, [1, config.group_size], -128, 127
188+
w2d, [1, config.group_size], qmin, qmax
181189
)
182190
qdata = qdata.to(torch.int8).reshape(weight.shape)
183191
scale = scale.to(torch.bfloat16).reshape(weight.shape[0], -1)
@@ -190,8 +198,8 @@ def _to_intx_tensor(
190198
mapping,
191199
block_size,
192200
target_dtype=torch.int8,
193-
quant_min=-128,
194-
quant_max=127,
201+
quant_min=qmin,
202+
quant_max=qmax,
195203
scale_dtype=torch.bfloat16,
196204
zero_point_dtype=torch.int8,
197205
)
@@ -201,8 +209,8 @@ def _to_intx_tensor(
201209
scale,
202210
zero_point,
203211
output_dtype=torch.int8,
204-
quant_min=-128,
205-
quant_max=127,
212+
quant_min=qmin,
213+
quant_max=qmax,
206214
)
207215
N, n_groups = weight.shape[0], weight.shape[-1] // config.group_size
208216
scale = scale.reshape(N, n_groups)
@@ -212,7 +220,7 @@ def _to_intx_tensor(
212220
qdata=qdata,
213221
scale=scale,
214222
zero_point=zero_point,
215-
target_dtype=torch.int8,
223+
target_dtype=target_dtype,
216224
block_size=(1, config.group_size),
217225
dtype=torch.bfloat16,
218226
activation_quantization=None,
@@ -222,9 +230,10 @@ def _to_intx_tensor(
222230
def quantize_weight(weight: torch.Tensor, config: QuantConfig) -> torch.Tensor:
223231
"""Quantize ``weight`` to a torchao tensor subclass.
224232
225-
Returns ``Int4Tensor`` for 4-bit or ``IntxUnpackedToInt8Tensor`` for 8-bit.
233+
Returns ``Int4Tensor`` for 4-bit or ``IntxUnpackedToInt8Tensor`` for 6-
234+
and 8-bit.
226235
"""
227-
if config.bits == 8:
236+
if config.bits in (6, 8):
228237
return _to_intx_tensor(weight, config)
229238

230239
if config.bits != 4:

examples/models/gemma4_31b/quant/recipe.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ class QuantConfig:
2424
carry their own metadata. This is purely for driving ``quantize_weight``.
2525
"""
2626

27-
bits: int # 4 or 8
27+
bits: int # 4, 6, or 8
2828
group_size: int
2929
symmetric: bool # True = no zero point
3030
method: str # "min_max" | "hqq"

0 commit comments

Comments
 (0)