Skip to content

[Fix][Relax][ONNX] Support symbolic dims in SAME auto_pad pooling - #20404

Open
LiRunGuo wants to merge 1 commit into
apache:mainfrom
LiRunGuo:fix/onnx-pool-same-pad-symbolic
Open

LiRunGuo wants to merge 1 commit into
apache:mainfrom
LiRunGuo:fix/onnx-pool-same-pad-symbolic

Conversation

@LiRunGuo

Copy link
Copy Markdown

The ONNX pool converter converted every input dimension to a Python int in order to resolve auto_pad=SAME_UPPER/SAME_LOWER, so MaxPool, AveragePool and LpPool failed with TypeError: int() argument must be ... not 'Var' whenever a spatial extent was symbolic. #20398 reports this for a dynamic-width MaxPool taken from PP-OCR.

The input extent is not actually needed in the reported case. Both SAME modes produce ceil(input / stride) outputs, so the total padding is (ceil(in / s) - 1) * s + dilated_kernel - in, which reduces to dilated_kernel - 1 when the stride is 1. This PR computes the padding from that formula in a single helper, Pool.get_same_pads, which only reads an extent when the stride is greater than 1. A symbolic extent combined with a non-unit stride still cannot be expressed as a static padding attribute, so it now raises OpAttributeUnImplemented with a message naming the dimension, instead of the TypeError.

Replacing the separate max-pool and avg-pool code paths with one spec-following helper also corrects two silent issues. MaxPool with SAME_LOWER derived the output extent with floor(in / stride) where the spec requires ceil, which gave wrong padding whenever the extent was not divisible by the stride. AveragePool ignored dilations when resolving auto_pad.

Tests compare against onnxruntime for extents that are not divisible by the stride, and cover symbolic batch and width dimensions for all three ops (structurally, and numerically with a concrete input). The dilated case is checked structurally against the output shape given by ONNX shape inference, because onnxruntime ignores dilation when resolving auto_pad and returns a smaller output than the model's inferred shape. When the kernel is smaller than the stride the spec formula yields negative padding; the helper clamps it to zero, and this path has no onnxruntime comparison because onnxruntime rejects such models.

Fixes #20398

The pool converter materialized every input dimension as a Python int to
derive SAME_UPPER/SAME_LOWER padding, so MaxPool/AveragePool/LpPool failed
with `int(Var)` on graphs with symbolic spatial extents (e.g. PP-OCR's
dynamic-width MaxPool). With unit stride the SAME padding is
`dilated_kernel - 1` regardless of the input extent, so compute it without
touching the shape and only require a static extent when stride > 1,
raising OpAttributeUnImplemented otherwise.

Unifying the max/avg paths into one spec-following helper also fixes two
silent correctness issues: MaxPool SAME_LOWER used floor(in / stride)
instead of ceil for the output extent, producing incorrect pads when the
extent is not divisible by the stride, and AveragePool ignored dilations
when resolving auto_pad.

Fixes apache#20398

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug][Relax][ONNX] Dynamic MaxPool SAME_UPPER attempts int(SizeVar)

1 participant