Skip to content

Fuse reduction + transpose of shared input (save full memory pass) #21

Description

@eellison

Problem

60 repros emit 2-3 kernels for the pattern:

permute_default = permute(x, [1, 0])     # weight grad [N, C] → [C, N]
sum_dim_int_list = sum(x, dim=[0])        # bias grad [N, C] → [C]

Both read the same large input. Current approach reads it twice (once per kernel). Fused kernel reads once, writes both outputs.

Verified Speedup

1.69x — fused Triton kernel hits 99% of memcopy SOL (0.103ms vs 0.174ms for torch.compile on f32[25216, 3072]).

Prototype: bench_fused_transpose_sum.py — tiles [64,64], uses tl.trans() for coalesced transpose write + tl.atomic_add for partial sum accumulation.

Root Cause in Inductor

The scheduler blocker is tiling_prevents_reduction_fusion at simd.py:1458-1470. select_tiling is called on the permute as a purely pointwise op (reduction_numel=1), returning a 2-tuple. The check expects a 3-tuple with r0_: 1 suffix.

However, initial attempt to add (numel2, rnumel2) to the accepted set didn't reduce kernel count — there may be an earlier rejection. Needs debug tracing through can_fuse to find the actual blocker.

Key Insight

The transpose store can happen INSIDE the reduction loop body. Each tile loaded for the reduction also gets written transposed. fits_in_main_body (simd.py:1493) already supports pointwise stores inside reduction loops when node_numel == numel * rnumel. The scheduler just needs to recognize the permute qualifies.

Impact

60 repros, tensors up to 6.6GB. Saves one full memory pass per repro.

Repros from #26

85 repros from the finalized #26 checklist.

Metadata

Metadata

Assignees

Labels

inductor_fusionInductor fusion/codegen kernel-count investigation

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions