Arm backend: Set fixed qparams for acos, asin and atanh#18288
Arm backend: Set fixed qparams for acos, asin and atanh#18288martinlsm wants to merge 3 commits intopytorch:mainfrom
Conversation
The main section of a python file should be at the bottom to ensure everything from the file itself has been defined before running it. Signed-off-by: Martin Lindström <Martin.Lindstroem@arm.com> Change-Id: Ia534109ff87c9966641a9932c9fff8f6de5050fc
In quantization_annotator.py, declare groups of ops as sets instead of lists. The reason is that they are only used for lookup, so this change improves the time complexity for such lookups. Signed-off-by: Martin Lindström <Martin.Lindstroem@arm.com> Change-Id: I93428108b863c3dd2d6f80feea08859c059c187a
acos, asin and atanh have shown to be problematic to quantize properly due to their limited input range between [-1, 1] (inclusively for asin and acos and exclusively for atanh). Before this patch, the approach for quantizing these ops was to use the quantization spec from the quantization config (typically a HistogramObserver if using deafult symmetric quantization config). This caused problems when calibrating the model with inputs close to -1 or 1, because they could land outside the valid range of the operator. When this happened, the resulting TABLE op set the output of these outliers to zero, which is not ideal. To mitigate this problem, use fixed quantization params for these ops by statically defining them in quantization_annotator.py. With this solution, we potentially lose a bit of numerical precision because the ops won't be affected by quantization calibration at all, but the resulting TABLE ops won't set any zeros since there is no input that can be outside the [-1, 1] interval anymore. Signed-off-by: Martin Lindström <Martin.Lindstroem@arm.com> Change-Id: Id55156be5ca7fcfbf9f9c3f8ae88fb075509ce0c
🔗 Helpful Links🧪 See artifacts and rendered test results at hud.pytorch.org/pr/pytorch/executorch/18288
Note: Links to docs will display an error until the docs builds have been completed. ❌ 2 Awaiting Approval, 1 New Failure, 1 Cancelled Job, 1 Pending, 3 Unrelated FailuresAs of commit c420531 with merge base b1373e8 ( AWAITING APPROVAL - The following workflows need approval before CI can run:
NEW FAILURE - The following job has failed:
CANCELLED JOB - The following job was cancelled. Please retry:
BROKEN TRUNK - The following jobs failed but were present on the merge base:👉 Rebase onto the `viable/strict` branch to avoid these failures
This comment was automatically generated by Dr. CI and updates every 15 minutes. |
|
@pytorchbot label ciflow/trunk |
|
@pytorchbot label "partner: arm" |
|
@pytorchbot label "release notes: none" |
There was a problem hiding this comment.
Pull request overview
This PR updates the Arm backend quantization annotator to use fixed input quantization parameters for select domain-restricted ops (acos/asin/atanh) and adjusts corresponding operator tests, aiming to reduce out-of-range issues and stabilize INT test behavior.
Changes:
- Add fixed-qparams input annotation path in
quantization_annotator.pyforaten.acos/asin/atanh. - Update acos/asin/atanh INT tests to rely on default similarity thresholds (and skip original-model comparison for atanh on invalid-domain inputs).
- Move
__main__example block inanalyze_output_utils.pyto the bottom of the file.
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| backends/arm/quantizer/quantization_annotator.py | Adds fixed-qparams quantization specs for acos/asin/atanh and refactors pattern containers to sets. |
| backends/arm/test/ops/test_atanh.py | Adjusts test vectors and conditionally skips original-model comparison at/over domain bounds. |
| backends/arm/test/ops/test_asin.py | Removes relaxed similarity thresholds to use pipeline defaults. |
| backends/arm/test/ops/test_acos.py | Removes relaxed Frobenius threshold to use pipeline defaults. |
| backends/arm/test/tester/analyze_output_utils.py | Relocates the __main__ example block to the end of the module. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| _fixed_input_qspec_ops: dict[Any, dict[int, _QParams]] = { | ||
| # acos has a valid range of [-1, 1] | ||
| torch.ops.aten.acos.default: { | ||
| 8: _QParams((1.0 - (-1.0)) / (1 << 8), 0), | ||
| 16: _QParams((1.0 - (-1.0)) / (1 << 16), 0), | ||
| }, | ||
| # asin has a valid range of [-1, 1] | ||
| torch.ops.aten.asin.default: { | ||
| 8: _QParams((1.0 - (-1.0)) / (1 << 8), 0), | ||
| 16: _QParams((1.0 - (-1.0)) / (1 << 16), 0), | ||
| }, | ||
| # atanh has a valid range of (-1, 1) (excluding -1 and 1). | ||
| torch.ops.aten.atanh.default: { | ||
| 8: _QParams((0.999 - (-0.999)) / (1 << 8), 0), | ||
| 16: _QParams((0.99999 - (-0.99999)) / (1 << 16), 0), |
| quant_properties.quant_output = _QuantProperty(0, output_act_qspec) | ||
| elif node.target in _fixed_input_qspec_ops: | ||
| num_bits = torch.iinfo(input_act_qspec.dtype).bits | ||
| qparams = _fixed_input_qspec_ops[node.target][num_bits] |
|
|
||
|
|
||
| if __name__ == "__main__": | ||
| """This is expected to produce the example output of print_diff.""" |
| ) | ||
| if torch.any(test_data >= 1) or torch.any(test_data <= -1): | ||
| # The quantized model will saturate to max/min values while the | ||
| # original model will return inf/-inf, so comparison wont be valid here. |
acos, asin and atanh have shown to be problematic to quantize properly
due to their limited input range between [-1, 1] (inclusively for asin
and acos and exclusively for atanh). Before this patch, the approach for
quantizing these ops was to use the quantization spec from the
quantization config (typically a HistogramObserver if using deafult
symmetric quantization config). This caused problems when calibrating
the model with inputs close to -1 or 1, because they could land outside
the valid range of the operator. When this happened, the resulting TABLE
op set the output of these outliers to zero, which is not ideal.
To mitigate this problem, use fixed quantization params for these ops by
statically defining them in quantization_annotator.py. With this
solution, we potentially lose a bit of numerical precision because the
ops won't be affected by quantization calibration at all, but the
resulting TABLE ops won't set any zeros since there is no input that
can be outside the [-1, 1] interval anymore.
Also, do some general improvements:
lists. The reason is that they are only used for lookup, so this change
improves the time complexity for such lookups.
cc @digantdesai @freddan80 @per @zingo @oscarandersson8218 @mansnils @Sebastian-Larsson @robell