Skip to content

Use one aggregate_impl for reducers with and without keep_dims - #2959

Open
gouarin wants to merge 1 commit into
xtensor-stack:masterfrom
gouarin:simplify-reducer-aggregate
Open

gouarin wants to merge 1 commit into
xtensor-stack:masterfrom
gouarin:simplify-reducer-aggregate

Conversation

@gouarin

@gouarin gouarin commented Oct 29, 2026

Copy link
Copy Markdown
Member

Checklist

  • The title and commit message(s) are descriptive.
  • Small commits made to fix your PR have been squashed to avoid history pollution.
  • Tests have been added for new features or bug fixes.
  • API of new functions and classes are documented (no public API changes).

Description

xreducer_stepper::aggregate_impl had a second overload for keep_dims. It walked every dimension of the expression, looked each one up in m_axes with std::find, and recursed through the dimensions that are not reduced without doing anything there. The other overload walks m_axes directly.

Both apply the same steps to the underlying stepper, since keep_dims only changes the shape of the result. The extra size != 0 test of the keep_dims overload is redundant too: aggregate() already returns the initial value for empty expressions. This PR removes the keep_dims overload.

GCC 13 at -O3 inlined that recursion and warned about m_e.shape()[dim] with dim == dimension() (-Warray-bounds, 18 occurrences in test_xmath). The axis checks in the constructor rule that path out, and the warning goes away with the overload.

xreducer.keep_dims_lazy_all_axes compares lazy keep_dims sums with immediate ones for every set of axes of a 4-D array, in row- and column-major order and with an initial value. It passes before and after the change, also under AddressSanitizer and UBSan.

xreducer_stepper::aggregate_impl had two overloads. The one used
without keep_dims walks the reduced axes, m_axes[0] to m_axes.back().
The keep_dims one walked every dimension of the expression, looked each
one up in m_axes with std::find, and recursed through the dimensions
that are not reduced without doing anything there.

Both do the same steps on the underlying stepper: keep_dims only
changes the shape of the result, which the stepper does not use here.
The extra size != 0 test of the keep_dims overload is also redundant,
since aggregate() returns the initial value for empty expressions
before calling aggregate_impl. The keep_dims overload is removed.

GCC 13 at -O3 inlined that recursion and warned about
m_e.shape()[dim] for dim == dimension() (-Warray-bounds), a path that
the axis validation in the constructor rules out. The warning goes away
with the overload.

The new test compares lazy keep_dims sums with immediate ones for
every set of axes of a 4-D array, in row and column major order and
with an initial value.
@codspeed

codspeed Bot commented Oct 29, 2026

Copy link
Copy Markdown
Contributor

Merging this PR will regress 1 benchmark

1 warning

⚠️ Unable to measure the execution of 1 benchmark

This benchmark measured no execution time, so its result is not comparable and counts as unchanged. This usually happens when the compiler removes the code under test.

Prevent compiler optimizations

See affected benchmarks

⚡ 4 improved benchmarks
❌ 1 regressed benchmark
✅ 250 untouched benchmarks

Warning

Please fix the performance issues or acknowledge them on CodSpeed.

Performance Changes

Benchmark BASE HEAD Efficiency
❌ xshape_initializer[std\:\:array<std\:\:size_t, 4>] 151.7 ns 180.8 ns -16.13%
⚡ xshape_access[std\:\:array<std\:\:size_t, 4>] 154.4 ns 125.3 ns +23.28%
⚡ reducer_reducer[100000x10 / axis 0] 12.7 ms 11.2 ms +12.88%
⚡ reducer_reducer[10x100000 / axis 0] 12.7 ms 11.2 ms +12.88%
⚡ reducer_reducer[10x100000 / axis 1] 8.1 ms 7.3 ms +11.48%

Tip

Investigate this regression by commenting @codspeedbot fix this regression on this PR, or directly use the CodSpeed MCP with your agent.


Comparing gouarin:simplify-reducer-aggregate (30bc8ea) with master (57f3d07)

Open in CodSpeed

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant