Arm backend: skip FoldScalarMulIntoConv when conv output feeds carried state (#21234)#21234
Arm backend: skip FoldScalarMulIntoConv when conv output feeds carried state (#21234)#212343l1 wants to merge 2 commits into
Conversation
🔗 Helpful Links🧪 See artifacts and rendered test results at hud.pytorch.org/pr/pytorch/executorch/21234
Note: Links to docs will display an error until the docs builds have been completed. ❗ 1 Active SEVsThere are 1 currently active SEVs. If your PR is affected, please view them below: ❌ 104 New Failures, 1 Cancelled Job, 13 Unrelated Failures, 8 Unclassified FailuresAs of commit b4c9793 with merge base 430b73d ( NEW FAILURES - The following jobs have failed:
UNCLASSIFIED FAILURES - DrCI could not classify the following jobs because the workflow did not run on the merge base. The failures may be pre-existing on trunk or introduced by this PR:
CANCELLED JOB - The following job was cancelled. Please retry:
FLAKY - The following jobs failed but were likely due to flakiness present on trunk:
This comment was automatically generated by Dr. CI and updates every 15 minutes. |
|
@3l1 has exported this pull request. If you are a Meta employee, you can view the originating Diff in D113310883. |
This PR needs a
|
2c508db to
247cdc5
Compare
…d state (#21234) Summary: FoldScalarMulIntoConv #20838 rewrites conv(x) * scale to a convolution with scaled weights. This is exact in floating point but moves the scaling inside the convolution, changing the conv output's quantization (its activation range and requantization). That is harmless for a plain feed-forward output, but if the scaled conv output feeds a carried/stateful quantization boundary -- a value written back into a mutable buffer / input that persists across invocations (recurrent state) -- the shifted requantization drifts the persisted quantized state and the error compounds over the sequence. Make the fold state-aware: skip it when the conv output transitively reaches a BUFFER_MUTATION / USER_INPUT_MUTATION output in the exported program's graph signature. Plain feed-forward convolutions are unaffected and still fold. Add StatefulConvMul (conv output * scale written into a mutable buffer) and assert the scalar mul survives. Differential Revision: D113310883
…d state (#21234) Summary: FoldScalarMulIntoConv #20838 rewrites conv(x) * scale to a convolution with scaled weights. This is exact in floating point but moves the scaling inside the convolution, changing the conv output's quantization (its activation range and requantization). That is harmless for a plain feed-forward output, but if the scaled conv output feeds a carried/stateful quantization boundary -- a value written back into a mutable buffer / input that persists across invocations (recurrent state) -- the shifted requantization drifts the persisted quantized state and the error compounds over the sequence. Make the fold state-aware: skip it when the conv output transitively reaches a BUFFER_MUTATION / USER_INPUT_MUTATION output in the exported program's graph signature. Plain feed-forward convolutions are unaffected and still fold. Add StatefulConvMul (conv output * scale written into a mutable buffer) and assert the scalar mul survives. Differential Revision: D113310883
247cdc5 to
ac47e4a
Compare
…d state (#21234) Summary: FoldScalarMulIntoConv #20838 rewrites conv(x) * scale to a convolution with scaled weights. This is exact in floating point but moves the scaling inside the convolution, changing the conv output's quantization (its activation range and requantization). That is harmless for a plain feed-forward output, but if the scaled conv output feeds a carried/stateful quantization boundary -- a value written back into a mutable buffer / input that persists across invocations (recurrent state) -- the shifted requantization drifts the persisted quantized state and the error compounds over the sequence. Make the fold state-aware: skip it when the conv output transitively reaches a BUFFER_MUTATION / USER_INPUT_MUTATION output in the exported program's graph signature. Plain feed-forward convolutions are unaffected and still fold. Add StatefulConvMul (conv output * scale written into a mutable buffer) and assert the scalar mul survives. Differential Revision: D113310883
ac47e4a to
6d60502
Compare
6d60502 to
4242879
Compare
…d state (#21234) Summary: Follow-up to D113310822, which documents (as a strict xfail) that FoldScalarMulIntoConv (#20838) is unsafe when the scaled conv output feeds a carried/stateful quantization boundary: the fold moves the scaling inside the convolution, shifting the conv output requant, which drifts a quantized value persisted across invocations (recurrent state) and compounds over the sequence. Make the fold state-aware and skip it in that case. Two carried-state signals are handled: - Structural: the conv output transitively reaches a BUFFER_MUTATION / USER_INPUT_MUTATION output in the exported program graph signature (mutable buffer / input mutation). - Explicit: a new mark_carried_quant_state / is_carried_quant_state marker (arm_pass_utils) a model can set on the (conv * scale) output. Functional recurrent state (state_in arg + state_out return, shared quantization) has no structural signal before quantization, so it needs an explicit marker. Plain feed-forward convolutions are unaffected and still fold. Un-xfails test_does_not_fold_when_output_feeds_stateful_buffer (the buffer-mutation case introduced in D113310822) and adds test_does_not_fold_when_output_marked_carried_state (the explicit-marker case). Differential Revision: D113310883
…d state (#21234) Summary: Follow-up to D113310822, which documents (as a strict xfail) that FoldScalarMulIntoConv (#20838) is unsafe when the scaled conv output feeds a carried/stateful quantization boundary: the fold moves the scaling inside the convolution, shifting the conv output requant, which drifts a quantized value persisted across invocations (recurrent state) and compounds over the sequence. Make the fold state-aware and skip it in that case. Two carried-state signals are handled: - Structural: the conv output transitively reaches a BUFFER_MUTATION / USER_INPUT_MUTATION output in the exported program graph signature (mutable buffer / input mutation). - Explicit: a new mark_carried_quant_state / is_carried_quant_state marker (arm_pass_utils) a model can set on the (conv * scale) output. Functional recurrent state (state_in arg + state_out return, shared quantization) has no structural signal before quantization, so it needs an explicit marker. Plain feed-forward convolutions are unaffected and still fold. Un-xfails test_does_not_fold_when_output_feeds_stateful_buffer (the buffer-mutation case introduced in D113310822) and adds test_does_not_fold_when_output_marked_carried_state (the explicit-marker case). Differential Revision: D113310883
4242879 to
a28b814
Compare
…d state (#21234) Summary: Follow-up to D113310822, which documents (as a strict xfail) that FoldScalarMulIntoConv (#20838) is unsafe when the scaled conv output feeds a carried/stateful quantization boundary: the fold moves the scaling inside the convolution, shifting the conv output requant, which drifts a quantized value persisted across invocations (recurrent state) and compounds over the sequence. Make the fold state-aware and skip it in that case. Two carried-state signals are handled: - Structural: the conv output transitively reaches a BUFFER_MUTATION / USER_INPUT_MUTATION output in the exported program graph signature (mutable buffer / input mutation). - Explicit: a new mark_carried_quant_state / is_carried_quant_state marker (arm_pass_utils) a model can set on the (conv * scale) output. Functional recurrent state (state_in arg + state_out return, shared quantization) has no structural signal before quantization, so it needs an explicit marker. Plain feed-forward convolutions are unaffected and still fold. Un-xfails test_does_not_fold_when_output_feeds_stateful_buffer (the buffer-mutation case introduced in D113310822) and adds test_does_not_fold_when_output_marked_carried_state (the explicit-marker case). Differential Revision: D113310883
a28b814 to
c34b085
Compare
…d state (#21234) Summary: Follow-up to D113310822, which documents (as a strict xfail) that FoldScalarMulIntoConv (#20838) is unsafe when the scaled conv output feeds a carried/stateful quantization boundary: the fold moves the scaling inside the convolution, shifting the conv output requant, which drifts a quantized value persisted across invocations (recurrent state) and compounds over the sequence. Make the fold state-aware and skip it in that case. Two carried-state signals are handled: - Structural: the conv output transitively reaches a BUFFER_MUTATION / USER_INPUT_MUTATION output in the exported program graph signature (mutable buffer / input mutation). - Explicit: a new mark_carried_quant_state / is_carried_quant_state marker (arm_pass_utils) a model can set on the (conv * scale) output. Functional recurrent state (state_in arg + state_out return, shared quantization) has no structural signal before quantization, so it needs an explicit marker. Plain feed-forward convolutions are unaffected and still fold. Un-xfails test_does_not_fold_when_output_feeds_stateful_buffer (the buffer-mutation case introduced in D113310822) and adds test_does_not_fold_when_output_marked_carried_state (the explicit-marker case). Differential Revision: D113310883
c34b085 to
63a9935
Compare
…hazard (#21152) Summary: FoldScalarMulIntoConv (#20838) rewrites conv(x) * scale into a convolution with scaled weights. This is exact in floating point (already covered by the existing tests in this file), but it is not safe under quantization when the scaled conv output feeds a carried/stateful quantization boundary -- a value written back into a mutable buffer / input that persists across invocations (recurrent state). Activation qparams are calibrated and frozen on the pre-fold conv output; folding the scale into the weights moves the scaling inside the convolution, so the conv output is requantized with the stale pre-fold scale. That shifted requantization drifts the persisted quantized state and the error compounds over the sequence. Add StatefulConvMul (conv output * scale written into a mutable buffer) and an xfail unit test (test_does_not_fold_when_output_feeds_stateful_buffer) documenting the hazard: the fold currently fires and drops the mul across the buffer boundary. The test is marked xfail (strict); the state-aware guard in D113310883 makes it pass, and the xfail is removed there. Reviewed By: rascani Differential Revision: D113310822
…d state (#21234) Summary: Follow-up to D113310822, which documents (as a strict xfail) that FoldScalarMulIntoConv (#20838) is unsafe when the scaled conv output feeds a carried/stateful quantization boundary: the fold moves the scaling inside the convolution, shifting the conv output requant, which drifts a quantized value persisted across invocations (recurrent state) and compounds over the sequence. Make the fold state-aware and skip it in that case. Two carried-state signals are handled: - Structural: the conv output transitively reaches a BUFFER_MUTATION / USER_INPUT_MUTATION output in the exported program graph signature (mutable buffer / input mutation). - Explicit: a new mark_carried_quant_state / is_carried_quant_state marker (arm_pass_utils) a model can set on the (conv * scale) output. Functional recurrent state (state_in arg + state_out return, shared quantization) has no structural signal before quantization, so it needs an explicit marker. Plain feed-forward convolutions are unaffected and still fold. Un-xfails test_does_not_fold_when_output_feeds_stateful_buffer (the buffer-mutation case introduced in D113310822) and adds test_does_not_fold_when_output_marked_carried_state (the explicit-marker case). Differential Revision: D113310883
63a9935 to
b4c9793
Compare
Summary:
Follow-up to D113310822, which documents (as a strict xfail) that
FoldScalarMulIntoConv (#20838) is unsafe
when the scaled conv output feeds a carried/stateful quantization boundary: the
fold moves the scaling inside the convolution, shifting the conv output requant,
which drifts a quantized value persisted across invocations (recurrent state) and
compounds over the sequence.
Make the fold state-aware and skip it in that case. Two carried-state signals are
handled:
USER_INPUT_MUTATION output in the exported program graph signature (mutable
buffer / input mutation).
(arm_pass_utils) a model can set on the (conv * scale) output. Functional
recurrent state (state_in arg + state_out return, shared quantization) has no
structural signal before quantization, so it needs an explicit marker.
Plain feed-forward convolutions are unaffected and still fold.
Un-xfails test_does_not_fold_when_output_feeds_stateful_buffer (the buffer-mutation
case introduced in D113310822) and adds
test_does_not_fold_when_output_marked_carried_state (the explicit-marker case).
Differential Revision: D113310883