Repository navigation
Swap reverse-broadcast operands once in handle_broadcast_elementwise - #24809
Conversation
When the left operand is the broadcast one, select_optimized_path picks a *ReverseArguments path and handle_broadcast_elementwise calls the lambda with the operands swapped. op_div and op_add_sub_impl swap their lambda for those paths, but op_le did not, so le(a, b) returned b <= a whenever the inputs and output shared a dtype. Swap the lambda the same way. The existing reverse broadcast tests use a Bool output, which routes to the portable path, so the new tests use a same-dtype output and Bool inputs to exercise the optimized paths. Fixes pytorch#24485 Authored with AI assistance (Claude Code).
On the *ReverseArguments paths, handle_broadcast_elementwise hands the broadcasting maps (b, a), so every non-commutative caller had to pass a hand-swapped lambda on those paths. op_div and op_add_sub_impl did, op_le did not (pytorch#24485). This swaps vec_fun's arguments once inside handle_broadcast_elementwise, so the lambda always receives (a, b), and removes the per-op swaps, resolving the TODO in op_add_sub_impl.h. op_mul is commutative, so it passes kCommutative = true to skip compiling the swapped copy, which would otherwise add about 16 KB to op_mul. With it, op_mul is unchanged and op_div/op_add/op_sub/op_le shrink slightly. Stacked on pytorch#24486, whose tests cover le on all three reverse paths; land after it. Test plan: optimized_kernels_test passes (1839 tests, unchanged). With the central swap disabled, 9 add/sub/div/le tests fail, so the existing tests cover the swap for every non-commutative caller. Authored with AI assistance (Claude Code).
🔗 Helpful Links🧪 See artifacts and rendered test results at hud.pytorch.org/pr/pytorch/executorch/24809
Note: Links to docs will display an error until the docs builds have been completed. ✅ No FailuresAs of commit aa54c1f with merge base 3f08f3f ( This comment was automatically generated by Dr. CI and updates every 15 minutes. |
This PR needs a
|
|
@claude review effort:max |
|
Claude finished @JakeStevens's task in 2m 32s —— View job I found no correctness bugs: on every broadcast path the lambda now gets Detailed reviewPR Review: #24809SummaryThis PR moves the reverse-broadcast operand swap into Backward Compatibility
API Design
Code Quality
Testing
RecommendationApprove: no blockers. Consider dropping the unused |
|
heads up,
looks like a merge race with #24486, which landed an hour before this one. it added its own swap for the reverse broadcast paths inside op_le.cpp. with the central swap in handle_broadcast_elementwise from this pr, le now swaps twice. the parent commit was green. dropping the reverse path branch from op_le.cpp (back to a single |
#24809 moved the reverse-broadcast operand swap into handle_broadcast_elementwise and removed the per-op swaps, but its op_le.cpp hunk was lost when it was squash-merged on top of #24486. op_le still passes its own swapped lambda on the *ReverseArguments paths, so the operands are swapped twice and le computes b <= a. This breaks OpLeTensorOutTest.BroadcastSameDtypeOut and BroadcastBoolInputs in optimized_kernels_test on main. Restores the missing hunk so op_le passes the plain x.le(y) lambda, like op_div and op_add_sub_impl. Test plan: optimized_kernels_test passes (1839 tests). Without this change, the two le tests above fail, matching CI. Authored with AI assistance (Claude Code).
Summary
On the
*ReverseArgumentspaths,handle_broadcast_elementwisehands the broadcasting maps(b, a), so every non-commutative caller had to pass a hand-swapped lambda on those paths.op_divandop_add_sub_impldid,op_ledid not (#24485). This swapsvec_fun's arguments once insidehandle_broadcast_elementwise, so the lambda always receives(a, b), and removes the per-op swaps, resolving the TODO inop_add_sub_impl.h.op_mulis commutative, so it passeskCommutative = trueto skip compiling the swapped copy, which would otherwise add about 16 KB toop_mul. With it,op_mulis unchanged andop_div/op_add/op_sub/op_leshrink slightly.Stacked on #24486, whose tests cover
leon all three reverse paths; land after it.Authored with AI assistance (Claude Code).
Test plan
optimized_kernels_testpasses (1839 tests, unchanged). With the central swap disabled, 9 add/sub/div/le tests fail, so the existing tests cover the swap for every non-commutative caller.