Skip to content

Numba: Fuse Elemwise + Reduction#2227

Open
ricardoV94 wants to merge 4 commits into
pymc-devs:mainfrom
ricardoV94:reduction_fusion_with_scope_markers
Open

Numba: Fuse Elemwise + Reduction#2227
ricardoV94 wants to merge 4 commits into
pymc-devs:mainfrom
ricardoV94:reduction_fusion_with_scope_markers

Conversation

@ricardoV94

Copy link
Copy Markdown
Member

Extends #2015 to also fuse CAReduce with Elemwise or IndexedELemwise (now renamed FusedElemwise).

This sometimes actually causes regressions without numba/llvmlite#895 as it prevents auto-vectorization numba was doing when the Ops weren't fused.

So I did the only logical thing and patched llvmlite from within PyTensor.

Results on the same benchmark we focused on for IndexedElemwise: https://ricardov94.github.io/pymc-model-catalogue/experiments.html#base=fuse_reduction_curated_base&compare=reduction_fusion_vs_nonfused

image

This is one of the ways in which JAX sometimes beats us on the CPU


if not idx_groups:
# Find reductions to fuse: an Elemwise output whose sole client is an
# eligible CAReduce. Outputs that are write targets are excluded (an

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why can't they be duplicated the same?

Comment thread tests/tensor/rewriting/test_math.py
@ricardoV94 ricardoV94 force-pushed the reduction_fusion_with_scope_markers branch from 777ed4c to 605789e Compare June 16, 2026 11:50
@aseyboldt

Copy link
Copy Markdown
Member

I had another look at the alias-scope metadata. This is a bit scary, because it would lead to quite strange problems if we get this wrong, and it is not easy to reason through properly, but it does look correct to me.

@ricardoV94 ricardoV94 force-pushed the reduction_fusion_with_scope_markers branch 3 times, most recently from 237f039 to 51d42ab Compare July 7, 2026 09:19
@ricardoV94 ricardoV94 marked this pull request as ready for review July 7, 2026 09:30
An output consumed by several eligible CAReduces previously disqualified
itself entirely (the detection required exactly one reduce client). Peel one
extra reduction per rewrite pass onto a duplicate output until each reduction
has its own copy, so e.g. [sum(f), max(f), prod(f), f] becomes a single
FusedElemwise with three fused reductions.
sum(x[idx]) had no Elemwise for FuseElemwise to anchor on, so the gather
materialized and the reduction stayed external. A new pre-rewrite wraps such
reductions in an identity Elemwise (covering the bare AdvancedSubtensor1,
axis-swap DimShuffle and flattened-ND-index Reshape forms), letting gather,
identity and reduction collapse into one fused loop.
@ricardoV94 ricardoV94 force-pushed the reduction_fusion_with_scope_markers branch from 51d42ab to 7fdc405 Compare July 7, 2026 12:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants