QnnQuantizer is a quantization annotator designed for QNN backends. It utilizes the rules_map found in the respective {backend}_rules.py file, which is a dictionary that links OpOverload to both annotator and validation functions. This mapping guides how each node is annotated and v
| 288 | |
| 289 | |
| 290 | class QnnQuantizer(Quantizer): |
| 291 | """ |
| 292 | QnnQuantizer is a quantization annotator designed for QNN backends. |
| 293 | It utilizes the rules_map found in the respective {backend}_rules.py file, |
| 294 | which is a dictionary that links OpOverload to both annotator and validation functions. |
| 295 | This mapping guides how each node is annotated and validated for quantization. |
| 296 | |
| 297 | During validation, the backend_opinfo pybind library containing operation details |
| 298 | from the QNN SDK is used to verify quantization constraints and maintain backend compatibility. |
| 299 | This library is available with QNN SDK version 2.41 or later. |
| 300 | If the library is unavailable, QnnQuantizer will not validate quantization constraints for operations. |
| 301 | |
| 302 | Args: |
| 303 | backend: QnnQuantizer uses the backend_type to dynamically load the appropriate backend rules as needed. |
| 304 | soc_model: QnnQuantizer checks each operation according to the soc_model. For example, LPBQ requires V69 or a newer version. |
| 305 | strict: |
| 306 | When enabled (default), the validation stage raises a ValueError if quantization constraints are not met. |
| 307 | In this mode, all quantization constraints must be satisfied to fully delegate to the QNN Backend. |
| 308 | When disabled, only warnings will be logged. |
| 309 | |
| 310 | Example usage: |
| 311 | quantizer = QnnQuantizer( |
| 312 | backend=QnnExecuTorchBackendType.kHtpBackend, |
| 313 | soc_model=QcomChipset.SM8750 |
| 314 | ) |
| 315 | quantizer.set_default_quant_config( |
| 316 | quant_dtype=QuantDtype.use_8a8w, |
| 317 | is_qat=False, |
| 318 | is_conv_per_channel=True, |
| 319 | is_linear_per_channel=True, |
| 320 | act_observer=MovingAverageMinMaxObserver, |
| 321 | ) |
| 322 | quantizer.set_block_size_map({"conv2d": (1, 128, 1, 1)}) |
| 323 | quantizer.set_submodule_qconfig_list([ |
| 324 | (get_submodule_type_predicate("Add"), ModuleQConfig(quant_dtype=QuantDtype.use_16a4w)) |
| 325 | ]) |
| 326 | quantizer.add_custom_quant_annotations(...) |
| 327 | quantizer.add_discard_nodes([node.name to skip annotation]) |
| 328 | quantizer.add_discard_ops([node.target to skip annotation]) |
| 329 | |
| 330 | """ |
| 331 | |
| 332 | def __init__( |
| 333 | self, |
| 334 | backend: QnnExecuTorchBackendType = QnnExecuTorchBackendType.kHtpBackend, |
| 335 | soc_model: QcomChipset = QcomChipset.SM8750, |
| 336 | strict: bool = True, |
| 337 | ): |
| 338 | super().__init__() |
| 339 | self.strict = strict |
| 340 | self.backend = str(backend) |
| 341 | self.soc_info = _soc_info_table[soc_model] |
| 342 | |
| 343 | # Lazy load rules and constraints of current backend |
| 344 | self._rules_map, self._constraint_cache = load_backend_rules_and_constraints( |
| 345 | self.backend |
| 346 | ) |
| 347 | self.supported_ops: Set[OpOverload] = set(self._rules_map.keys()) |
no outgoing calls