Skip to content

Commit 69d9a53

Browse files
committed
refactor: add validate_coreml_palettization_compatibility for combo checks
Vector palettization, LUT quantization, and per-channel scale are each independently CoreML-exportable, but combining any two breaks CoreML/MIL's constexpr_lut_to_dense op with a rank mismatch, a missing vector_axis, or an indices/LUT divisibility error depending on the pair. Add a dedicated validator (composing the existing LUT dtype check) so the kmeans export path has one entry point to reject these combinations with a clear CoreMLExportError, instead of relying on a test-side skip to hide them.
1 parent 56c4a36 commit 69d9a53

1 file changed

Lines changed: 47 additions & 0 deletions

File tree

src/coreai_opt/_utils/export_utils.py

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
from coreai_opt._utils.torch_utils import is_tensor_on_cpu
1212
from coreai_opt.common import CoreMLExportError, ExportBackend
1313
from coreai_opt.config.spec import CompressionTargetTensor
14+
from coreai_opt.quantization.spec import QuantizationSpec
1415
from coreai_opt.quantization.spec.granularity import PerTensorGranularity, QuantizationGranularity
1516

1617
COREML_SUPPORTED_WEIGHT_DTYPES: frozenset[torch.dtype] = frozenset(
@@ -78,6 +79,52 @@ def validate_coreml_compatibility(
7879
raise CoreMLExportError.from_config(granularity, context)
7980

8081

82+
def validate_coreml_palettization_compatibility(
83+
cluster_dim: int,
84+
lut_qspec: QuantizationSpec | None,
85+
enable_per_channel_scale: bool,
86+
context: str,
87+
) -> None:
88+
"""Raise CoreMLExportError if this palettization config isn't CoreML-exportable.
89+
90+
Checks the LUT dtype (delegating to validate_coreml_compatibility) and
91+
whether the config combines multiple features CoreML/MIL export cannot yet
92+
fuse into a single compatible op chain: CoreML export supports at most one
93+
of {vector palettization, LUT quantization, per-channel scale} at a time;
94+
combining any two hits an unsupported CoreML/MIL op configuration
95+
(mismatched tensor ranks, or `lut_to_dense` divisibility errors).
96+
97+
Args:
98+
cluster_dim (int): Palettization cluster dimension; > 1 indicates
99+
vector palettization.
100+
lut_qspec (QuantizationSpec | None): LUT quantization spec, or None if
101+
the LUT is not quantized.
102+
enable_per_channel_scale (bool): Whether per-channel scaling is enabled.
103+
context (str): Human-readable description of what's being checked.
104+
105+
Raises:
106+
CoreMLExportError: If the LUT dtype isn't supported, or if two or more
107+
of the three features above are combined.
108+
"""
109+
if lut_qspec is not None:
110+
validate_coreml_compatibility(
111+
CompressionTargetTensor.LUT, lut_qspec.dtype, f"LUT of {context}"
112+
)
113+
114+
active_features = []
115+
if cluster_dim > 1:
116+
active_features.append("vector palettization")
117+
if lut_qspec is not None:
118+
active_features.append("LUT quantization")
119+
if enable_per_channel_scale:
120+
active_features.append("per-channel scale")
121+
122+
if len(active_features) >= 2:
123+
raise CoreMLExportError(
124+
f"CoreML export does not support {' + '.join(active_features)} on {context}."
125+
)
126+
127+
81128
def validate_mmap_backend_and_device(
82129
model: torch.nn.Module,
83130
backend: ExportBackend,

0 commit comments

Comments
 (0)