Skip to content

Commit e34a846

Browse files
committed
address review comments
1 parent f1fc652 commit e34a846

5 files changed

Lines changed: 33 additions & 35 deletions

File tree

src/coreai_opt/quantization/_eager/_prepare_for_export.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -199,9 +199,11 @@ def _import_coreai_torch_modules():
199199
CompressionTargetTensor.ACTIVATION,
200200
):
201201
if is_float4_dtype(module.dtype):
202-
raise ValueError("FP4 activation quantization is not supported for MLIR export.")
202+
raise ValueError("Core AI export does not support FP4 activation quantization.")
203203
if isinstance(module.granularity, PerBlockGranularity):
204-
raise ValueError("MLIR export does not support PerBlockGranularity on activations.")
204+
raise ValueError(
205+
"Core AI export does not support PerBlockGranularity on activations."
206+
)
205207
modules_to_replace.append((name, module))
206208

207209
# Replace each FakeQuantizeImplBase module

src/coreai_opt/quantization/_graph/_prepare_for_export.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -337,10 +337,10 @@ def _process_mlir_activation_quantization(
337337
fake_quant_mod: The fake quantization module
338338
"""
339339
if is_float4_dtype(fake_quant_mod.dtype):
340-
raise ValueError("FP4 activation quantization is not supported for MLIR export.")
340+
raise ValueError("Core AI export does not support FP4 activation quantization.")
341341

342342
if isinstance(fake_quant_mod.granularity, PerBlockGranularity):
343-
raise ValueError("MLIR export does not support PerBlockGranularity on activations.")
343+
raise ValueError("Core AI export does not support PerBlockGranularity on activations.")
344344

345345
def _import_coreai_custom_ops():
346346
import coreai_torch._compression.custom_layers # noqa: PLC0415, F401

src/coreai_opt/quantization/spec/factory.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -208,7 +208,6 @@ def create_fake_quantizer(
208208
"quant_min": spec.quant_min,
209209
"quant_max": spec.quant_max,
210210
"qparams_calculator": qparams_calculator,
211-
"quantization_target": quantization_target,
212211
"n_bits": spec.n_bits,
213212
}
214213

@@ -289,7 +288,6 @@ def create_fake_quantizer_partial(
289288
"target_dtype": spec.target_dtype,
290289
"quant_min": spec.quant_min,
291290
"quant_max": spec.quant_max,
292-
"quantization_target": quantization_target,
293291
"n_bits": spec.n_bits,
294292
}
295293

src/coreai_opt/quantization/spec/fake_quantize.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,6 @@ def __init__(
5353
quant_min: int | float,
5454
quant_max: int | float,
5555
qparams_calculator: QParamsCalculatorBase,
56-
quantization_target: CompressionTargetTensor,
5756
n_bits: int | None = None,
5857
**kwargs,
5958
):
@@ -65,7 +64,6 @@ def __init__(
6564
self.quant_min = quant_min
6665
self.quant_max = quant_max
6766
self.qparams_calculator = qparams_calculator
68-
self.quantization_target = quantization_target
6967
self.register_buffer("_disabled", torch.tensor(False))
7068

7169
# Infer n_bits from dtype if not provided
@@ -78,6 +76,11 @@ def qscheme(self) -> QuantizationScheme:
7876
"""The quantization scheme, delegated to the qparams_calculator."""
7977
return self.qparams_calculator.qscheme
8078

79+
@property
80+
def quantization_target(self) -> CompressionTargetTensor:
81+
"""Getter for quantization target."""
82+
return self.qparams_calculator.quantization_target
83+
8184
@property
8285
def granularity(self) -> QuantizationGranularity:
8386
"""Getter for granularity."""

src/coreai_opt/quantization/spec/granularity.py

Lines changed: 22 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -67,9 +67,9 @@ def _get_block_size(
6767
size for that specific axis
6868
6969
``quantization_target`` distinguishes weight from activation tensors.
70-
Only per-block granularity uses it (see
71-
:meth:`PerBlockGranularity._handle_single_axis_block_size`); the other
72-
granularities ignore it.
70+
Only per-block granularity uses it, since the two targets collapse
71+
different sets of non-blocked axes (see :class:`PerBlockGranularity`);
72+
the other granularities ignore it.
7373
7474
Example:
7575
- ``[10, 5, 2]`` with per-channel structuring on axis 1 results in
@@ -212,10 +212,15 @@ class PerBlockGranularity(QuantizationGranularity):
212212
``Quantizer.prepare()`` automatically resolves the axis based on the module type
213213
for weight quantization.
214214
215-
Single-axis mode treats weights and activations differently. For weights only
216-
the two leading channel axes participate in blocking, so trailing kernel
217-
dimensions span a whole block. For activations every axis other than the block
218-
axis gets its own scale.
215+
Single-axis mode treats weights and activations differently:
216+
217+
- ``WEIGHT``: only the two leading channel axes take part. Whichever of them
218+
is not the block axis collapses to ``1`` (one scale per slice), while
219+
trailing dimensions — e.g. conv kernel dims — keep their full size, so each
220+
block spans the whole kernel.
221+
- ``ACTIVATION``: every axis other than the block axis collapses to ``1``, so
222+
the scale holds one entry per block *and* per position along all the other
223+
axes.
219224
220225
.. list-table::
221226
:header-rows: 1
@@ -303,15 +308,20 @@ def _handle_single_axis_block_size(
303308
block_sizes_list: list[int],
304309
quantization_target: _CompressionTargetTensor = _CompressionTargetTensor.WEIGHT,
305310
) -> list[int]:
306-
"""Handle blocking when self.block_size is an integer"""
311+
"""Handle blocking when ``block_size`` is an integer.
312+
313+
``axis`` may be negative and is resolved against the tensor rank.
314+
315+
``quantization_target`` decides which of the non-blocked axes collapse to
316+
``1``: weights keep their trailing (e.g. kernel) dimensions whole, while
317+
activations collapse every axis but the block axis. See the class
318+
docstring for examples.
319+
"""
307320
# TODO: Logic to be added where if self.axis is None,
308321
# we can figure out the optimal axis for the user
309322
if self.axis is None:
310323
raise ValueError("axis must be specified when block_size is an int")
311324

312-
# Resolve negative (Python-style) axis to a non-negative index using the
313-
# tensor rank. This allows activation quantization to target the last /
314-
# reduction axis via axis=-1 regardless of the tensor's rank.
315325
rank = len(block_sizes_list)
316326
axis = self.axis + rank if self.axis < 0 else self.axis
317327

@@ -327,22 +337,7 @@ def _handle_single_axis_block_size(
327337
f"is not divisible by block size {self.block_size}"
328338
)
329339

330-
# How the non-block axes are treated depends on the quantization target,
331-
#
332-
# WEIGHT: only the two leading channel axes participate. The other
333-
# channel axis becomes 1 (one scale per slice) while any trailing
334-
# dimensions (index 2+, e.g. conv kernel dims) keep their full size so
335-
# each block spans the whole kernel.
336-
# [C_out, C_in, KH, KW], axis=0, block=16 -> [16, 1, KH, KW]
337-
#
338-
# ACTIVATION: blocking runs along a single axis and every other
339-
# dimension gets its own scale, so all non-block axes become 1.
340-
# [B, S, D], axis=-1, block=16 -> [1, 1, 16]
341-
# [B, C, H, W], axis=1, block=16 -> [1, 16, 1, 1]
342-
if quantization_target == _CompressionTargetTensor.ACTIVATION:
343-
collapse_upto = rank
344-
else:
345-
collapse_upto = 2
340+
collapse_upto = rank if quantization_target == _CompressionTargetTensor.ACTIVATION else 2
346341

347342
block_sizes_list[axis] = self.block_size
348343
for i, _ in enumerate(block_sizes_list[:collapse_upto]):

0 commit comments

Comments
 (0)