Uh oh!
There was an error while loading. Please reload this page.
Delegate even-kernel 'same'-padding convs via a quantized static pad (#20553) - #20553
Conversation
🔗 Helpful Links🧪 See artifacts and rendered test results at hud.pytorch.org/pr/pytorch/executorch/20553
Note: Links to docs will display an error until the docs builds have been completed. ❌ 1 New Failure, 1 Pending, 2 Unrelated FailuresAs of commit 0e81ab4 with merge base 3801496 ( NEW FAILURE - The following job has failed:
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. |
@JakeStevens has exported this pull request. If you are a Meta employee, you can view the originating Diff in D109871964. |
…ytorch#20553) Summary: When using padding="same" for a conv with even kernels, `torch.export` creates an explicit pad node, leading to a dq -> pad -> conv chain, which is not recognized, so conv ends up undelegated. The ReLU ends up in its own partition with a quantize. XNNPACK does not support this, resulting in `xnn_status_unsupported_parameter`. This PR fixes this, allowing for full delegation to XNNPACK in this case, by pulling the zero-valued spatial pad into the conv's partition (`ConvConfig._get_act_deps`) so both delegate together: for fp32 the pad lowers directly as an `XNNStaticConstantPad`. For quantized graphs the pad is created by `to_edge` decomposition after the quantizer runs, so it arrives as `dq -> pad -> conv` with no quantize on its output and would serialize as fp32 (the conv would then reject its unquantized activation). `InsertPadQDQPass` inserts an implicit `quantize -> dequantize` after the pad, reusing the feeding dequant's params (a zero pad preserves quantization), so it lowers as a quantized static pad and the conv sees a proper dequantized activation. Note: This results in full delegation, an improvement over the existing runtime error (or portable fallback as naive fix), but the pad is executed as a separate op and results in overhead. Differential Revision: D109871964
a04093b to
3c5db00Compare…ytorch#20553) Summary: When using padding="same" for a conv with even kernels, `torch.export` creates an explicit pad node, leading to a dq -> pad -> conv chain, which is not recognized, so conv ends up undelegated. The ReLU ends up in its own partition with a quantize. XNNPACK does not support this, resulting in `xnn_status_unsupported_parameter`. This PR fixes this, allowing for full delegation to XNNPACK in this case, by pulling the zero-valued spatial pad into the conv's partition (`ConvConfig._get_act_deps`) so both delegate together: for fp32 the pad lowers directly as an `XNNStaticConstantPad`. For quantized graphs the pad is created by `to_edge` decomposition after the quantizer runs, so it arrives as `dq -> pad -> conv` with no quantize on its output and would serialize as fp32 (the conv would then reject its unquantized activation). `InsertPadQDQPass` inserts an implicit `quantize -> dequantize` after the pad, reusing the feeding dequant's params (a zero pad preserves quantization), so it lowers as a quantized static pad and the conv sees a proper dequantized activation. Note: This results in full delegation, an improvement over the existing runtime error (or portable fallback as naive fix), but the pad is executed as a separate op and results in overhead. Differential Revision: D109871964
3c5db00 to
f94078bCompare…ytorch#20553) Summary: When using padding="same" for a conv with even kernels, `torch.export` creates an explicit pad node, leading to a dq -> pad -> conv chain, which is not recognized, so conv ends up undelegated. The ReLU ends up in its own partition with a quantize. XNNPACK does not support this, resulting in `xnn_status_unsupported_parameter`. This PR fixes this, allowing for full delegation to XNNPACK in this case, by pulling the zero-valued spatial pad into the conv's partition (`ConvConfig._get_act_deps`) so both delegate together: for fp32 the pad lowers directly as an `XNNStaticConstantPad`. For quantized graphs the pad is created by `to_edge` decomposition after the quantizer runs, so it arrives as `dq -> pad -> conv` with no quantize on its output and would serialize as fp32 (the conv would then reject its unquantized activation). `InsertPadQDQPass` inserts an implicit `quantize -> dequantize` after the pad, reusing the feeding dequant's params (a zero pad preserves quantization), so it lowers as a quantized static pad and the conv sees a proper dequantized activation. Note: This results in full delegation, an improvement over the existing runtime error (or portable fallback as naive fix), but the pad is executed as a separate op and results in overhead. Differential Revision: D109871964
f94078b to
e46184bCompare…ytorch#20553) Summary: When using padding="same" for a conv with even kernels, `torch.export` creates an explicit pad node, leading to a dq -> pad -> conv chain, which is not recognized, so conv ends up undelegated. The ReLU ends up in its own partition with a quantize. XNNPACK does not support this, resulting in `xnn_status_unsupported_parameter`. This PR fixes this, allowing for full delegation to XNNPACK in this case, by pulling the zero-valued spatial pad into the conv's partition (`ConvConfig._get_act_deps`) so both delegate together: for fp32 the pad lowers directly as an `XNNStaticConstantPad`. For quantized graphs the pad is created by `to_edge` decomposition after the quantizer runs, so it arrives as `dq -> pad -> conv` with no quantize on its output and would serialize as fp32 (the conv would then reject its unquantized activation). `InsertPadQDQPass` inserts an implicit `quantize -> dequantize` after the pad, reusing the feeding dequant's params (a zero pad preserves quantization), so it lowers as a quantized static pad and the conv sees a proper dequantized activation. Note: This results in full delegation, an improvement over the existing runtime error (or portable fallback as naive fix), but the pad is executed as a separate op and results in overhead. Differential Revision: D109871964
e46184b to
0d1649dCompare| An even-kernel 'same'-padding conv decomposes (after quantization) into | ||
| dequant -> constant_pad_nd -> convolution. Because the pad is introduced by | ||
| to_edge decomposition -- after the quantizer has run -- it is never annotated, |
There was a problem hiding this comment.
can we fuse it inside the preprocess for xnnpack or we have to run pad + conv in the XNNPACK graph? I am asking because if we can fuse it we might as well write that pass instead.
There was a problem hiding this comment.
We can fuse, I have some work in that direction, was going to publish as a quick follow up since there is an external contributor with the 1d work and the change is slightly larger so preferred to do it once these both land.
…ytorch#20553) Summary: When using padding="same" for a conv with even kernels, `torch.export` creates an explicit pad node, leading to a dq -> pad -> conv chain, which is not recognized, so conv ends up undelegated. The ReLU ends up in its own partition with a quantize. XNNPACK does not support this, resulting in `xnn_status_unsupported_parameter`. This PR fixes this, allowing for full delegation to XNNPACK in this case, by pulling the zero-valued spatial pad into the conv's partition (`ConvConfig._get_act_deps`) so both delegate together: for fp32 the pad lowers directly as an `XNNStaticConstantPad`. For quantized graphs the pad is created by `to_edge` decomposition after the quantizer runs, so it arrives as `dq -> pad -> conv` with no quantize on its output and would serialize as fp32 (the conv would then reject its unquantized activation). `InsertPadQDQPass` inserts an implicit `quantize -> dequantize` after the pad, reusing the feeding dequant's params (a zero pad preserves quantization), so it lowers as a quantized static pad and the conv sees a proper dequantized activation. Note: This results in full delegation, an improvement over the existing runtime error (or portable fallback as naive fix), but the pad is executed as a separate op and results in overhead. Differential Revision: D109871964
0d1649d to
0e81ab4CompareUh oh!
There was an error while loading. Please reload this page.
approach) Instead of folding constant_pad_nd into asymmetric Conv2d padding, keep it as an explicit XNNPACK pad op: - Remove pad-folding logic from Conv1dUnsqueezePass - Remove Conv1dFoldedPadMetaPass (no longer needed) - Revert xnnpack_input_padding handling in op_conv2d.py - Add InsertPadQDQPass: inserts QDQ after pad in quantized contexts so it serializes as a quantized static pad This matches the approach from pytorch#20553 and fixes the crash with conv1d -> flatten (even kernel + same padding).
approach) Instead of folding constant_pad_nd into asymmetric Conv2d padding, keep it as an explicit XNNPACK pad op: - Remove pad-folding logic from Conv1dUnsqueezePass - Remove Conv1dFoldedPadMetaPass (no longer needed) - Revert xnnpack_input_padding handling in op_conv2d.py - Add InsertPadQDQPass: inserts QDQ after pad in quantized contexts so it serializes as a quantized static pad This matches the approach from pytorch#20553 and fixes the crash with conv1d -> flatten (even kernel + same padding).
Fixes#20558. Related to #20553. ## Summary Quantized `nn.Conv1d(..., padding="same")` with an even kernel exports with asymmetric padding (unequal left/right amounts), which cannot be folded into the convolution's symmetric padding field. The original pad-folding approach in this PR was replaced with the explicit-PAD approach from #20553: - **InsertPadQDQPass** — inserts implicit quantize/dequantize pairs after constant_pad_nd nodes in quantized contexts so they serialize as quantized static pads. Refactored with additional guard checks (pad_value, pad_amounts, negative amounts) and correct idempotency. - **ConvolutionConfig._get_act_deps** — pulls zero-valued constant_pad_nd nodes (and their QDQ chain if InsertPadQDQPass already ran) into the convolution's partition for both 1D and 2D convs. The merged method replaces separate 1D and 2D implementations that existed on this branch. - **Regression test** — quantized Conv1d even-kernel same-padding covering both symmetric and asymmetric pad cases, validated by numerical comparison. - Removed unrelated __init__.py re-ordering and no-op conv1d_unsqueeze_pass changes. With these changes, an even-kernel `padding="same"` conv1d graph: ``` dequant -> constant_pad_nd -> convolution ``` becomes (after XNNPACK preprocessing and partitioning): ``` [dequant -> pad -> q -> dq -> conv] (single XNNPACK delegate) ``` ## Test plan ``` python -m pytest backends/xnnpack/test/ops/test_conv1d.py -q # 7 passed (1 new regression test with 4 subTests) python -m pytest backends/xnnpack/test/ops/test_conv2d.py -q # 32 passed python -m pytest backends/xnnpack/test/passes/test_insert_pad_qdq.py -q # 3 passed python -m pytest backends/xnnpack/test/ops/test_static_constant_pad.py -q # 8 passed lintrunner -a # No lint issues ``` cc @GregoryComer@digantdesai@cbilgin@JakeStevens@freddan80@per@zingo@oscarandersson8218@mansnils@Sebastian-Larsson@robell@rascani --------- Co-authored-by: Jacob Stevens <stevens.jacob1492@gmail.com>
Summary:
When using padding="same" for a conv with even kernels,
torch.exportcreates an explicit pad node, leading to a dq -> pad -> conv chain, which is not recognized, so conv ends up undelegated. The ReLU ends up in its own partition with a quantize. XNNPACK does not support this, resulting inxnn_status_unsupported_parameter.This PR fixes this, allowing for full delegation to XNNPACK in this case, by pulling the zero-valued spatial pad into the conv's partition (
ConvConfig._get_act_deps) so both delegate together: for fp32 the pad lowers directly as anXNNStaticConstantPad. For quantized graphs the pad is created byto_edgedecomposition after the quantizer runs, so it arrives asdq -> pad -> convwith no quantize on its output and would serialize as fp32 (the conv would then reject its unquantized activation).InsertPadQDQPassinserts an implicitquantize -> dequantizeafter the pad, reusing the feeding dequant's params (a zero pad preserves quantization), so it lowers as a quantized static pad and the conv sees a proper dequantized activation.Note: This results in full delegation, an improvement over the existing runtime error (or portable fallback as naive fix), but the pad is executed as a separate op and results in overhead.
Differential Revision: D109871964