[Fix][Relax][Frontend][ONNX] Support broadcastable multi-axis PRelu slopes - #20149
Open
siyiweigeHEW wants to merge 1 commit into
Open
[Fix][Relax][Frontend][ONNX] Support broadcastable multi-axis PRelu slopes#20149siyiweigeHEW wants to merge 1 commit into
siyiweigeHEW wants to merge 1 commit into
Conversation
PRelu._impl_v1 only accepted a slope with a single non-broadcast axis. A valid ONNX PRelu whose slope is broadcastable to x across multiple axes (e.g. a slope shaped like x, or with several non-broadcast dims) was rejected with ValueError 'Invalid PRelu slope shape (multiple non-broadcast dims)'. onnxruntime and onnx.reference both accept and run such models correctly. nn.prelu can only express a single per-axis slope, so lower the multi-axis case elementwise as PRelu(x, s) = where(x < 0, s * x, x) via relax.op.where/less/multiply. The single non-broadcast axis and all-ones/slope-of-rank-1 cases keep using nn.prelu unchanged. Together with apache#20115 (lower-rank and rank-0 slopes), all unidirectionally broadcastable slope shapes accepted by onnxruntime now import. Co-Authored-By: Claude <noreply@anthropic.com>
tlopex
requested changes
Aug 18, 2026
tlopex
left a comment
Member
There was a problem hiding this comment.
Could you add an in-tree test that actually covers this branch, for example X=(2,3,4,5) with slope=(4,5)? The current tests don’t exercise it.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes: #20148
Summary
The Relax ONNX frontend
PRelu._impl_v1rejected a validPReluwhoseslopeis broadcastable to
Xacross multiple non-broadcast axes (e.g. a slopeshaped exactly like
X, or with several non-1 dims) with aValueError, eventhough onnxruntime and
onnx.referenceaccept and run such models correctly.After #20115 added lower-rank and rank-0 slope support, this was the remaining
gap for unidirectionally broadcastable slopes.
Root cause
PRelu._impl_v1lowers a slope with a single non-broadcast axis torelax.op.nn.prelu(x, slope_vec, axis), which is the only shape Relax'snn.prelucan express (one per-axis slope vector). A slope that broadcastsalong several axes (
slope == X,(1, C, H, W),(N, C, 1, 1), …) cannot berepresented that way, so the code raised instead of lowering the op:
Fix
For the multi-non-broadcast case, lower
PReluelementwise instead:This is exactly
PRelu(x, s) = where(x < 0, s * x, x)withsbroadcast tox. The all-ones / rank-1 / single-non-broadcast paths are unchanged and stilluse
nn.prelu. Non-broadcastable slopes (rank > x, or a non-1 dim that does notmatch
x) still fail at build time with a broadcast error, consistent withonnxruntime rejecting them at session creation.
Validation
Differential test: Relax (build +
VirtualMachine) vs onnxruntime on the samemodel, comparing output shapes and max |diff| (cross-checked with
onnx.reference), across 7Xshapes × every valid broadcastableslope.(64,1,1)on(1,64,128,128)(1,64,128,128)(1,64,128,128)(2,3,4,5)(2,3,4,5)slope == X(2,3,4,5)(2,3,4,5)(1,3,4,5)(2,3,4,5)(2,3,4,5)(4,5)(2,3,4,5)(2,3,4,5)(1,1,4,1)(regression)(2,3,4,5)(2,3,4,5)(5,)/ all-ones (regression)(2,3,4,5)(2,3,4,5)Total: 113 valid cases (onnxruntime-accepted), 113 OK, 0 rejected, 0 numeric
mismatches (pre-fix: 46 OK / 67 rejected). The motivating Real-ESRGAN case
X(1,64,128,128)+slope(64,1,1)now imports and matches onnxruntime exactly.Run:
Files changed
python/tvm/relax/frontend/onnx/onnx_frontend.py—PRelu._impl_v1: elementwisewhere(x < 0, s * x, x)fallback for multi-non-broadcast slopes.