Broadcast elementwise flops from the trailing dimension - #8324
Broadcast elementwise flops from the trailing dimension#8324vineethsaivs wants to merge 1 commit into
Conversation
_elementwise_flops_compute walks both operand shapes from index 0 and pads the shorter one on the right. Broadcasting lines shapes up from the trailing dimension and pads on the left, so whenever the two operands differ in rank the counter builds a shape the result never has and reports flops for it. Multiplying a [2, 3, 4] activation by a [4] bias was counted over [4, 3, 4], 48 flops for an operation that touches 24 elements; [8] against [2, 8] was counted over [8, 8], 64 instead of 16. Ranks that already match were counted correctly, which is why the error hides: the pattern that trips it is the common one of scaling or shifting an activation by a per-feature vector. torch.broadcast_shapes gives the result shape directly, so the hand-rolled loop goes. Add a CPU regression test over matched and mismatched ranks that checks the count against the number of elements torch itself produced. Signed-off-by: Vineeth Sai <vineethsai4444@gmail.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: cc816116c6
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| # unrelated dimensions and yields a shape the result never has: multiplying a | ||
| # [2, 3, 4] activation by a [4] bias was counted over [4, 3, 4], twice the | ||
| # elements the operation touches. | ||
| return _prod(torch.broadcast_shapes(input.shape, other.shape)), 0 |
There was a problem hiding this comment.
Add the required Signed-off-by trailer
This non-merge commit's message does not include a Signed-off-by: trailer, while the repository requires every non-merge commit to be signed off. DCO/CI checks can reject the change until the commit is recreated or amended with --signoff.
AGENTS.md reference: AGENTS.md:L8-L8
Useful? React with 👍 / 👎.
Symptom
The flops profiler counts an elementwise
mul/addover the wrong shape whenever the two operands differ in rank, which is exactly the common case of scaling or shifting an activation by a per-feature vector.[2, 3, 4] * [4][4] * [2, 3, 4][8] * [2, 8][3, 4] * [4][2, 3, 4] * [2, 3, 4][4, 1, 7] * [1, 5, 7]Root cause
_elementwise_flops_computebuilds the result shape by walking both operands from index 0 and padding the shorter one on the right:Broadcasting lines shapes up from the trailing dimension and pads on the left. For
[2, 3, 4]against[4]the loop pairs 2 with 4, then 3 with the pad, then 4 with the pad, producing[4, 3, 4]rather than[2, 3, 4].Equal ranks are handled correctly, which is why this is easy to miss: the shape only comes out wrong when the ranks differ, and it can land either high or low depending on which dimensions get paired up. It happens to be right by coincidence when the mispaired dimensions have the same product, e.g.
[16] * [32, 16]gives[16, 32].The counter backs
torch.mul,torch.Tensor.mul,torch.addandtorch.Tensor.add.Fix
torch.broadcast_shapesreturns the result shape directly, so the hand-rolled loop goes. The two non-tensor branches above it are unchanged, and a 0-dim tensor operand still resolves to the other operand's shape.Test
tests/unit/profiling/flops_profiler/test_flops_profiler.py::test_elementwise_broadcast_flops, parametrized over four mismatched-rank pairs and two matched-rank pairs (one of them exercising a size-1 dimension). The expected value isresult.numel()from the tensor torch actually produced, so it is not a restatement of the implementation.Against master: 4 failed, 4 passed (
assert 48 == 24,assert 64 == 16,assert 16 == 12). With the fix: 8 passed.Also checked by hand and matching torch: a python scalar operand,
Tensor.mul,torch.add, a 0-dim tensor operand, and a scalar in the first position.Independent of #8323, which fixes
_conv_trans_flops_computein the same file. The two touch different functions and do not overlap.