Skip to content

Trunc fast - #1

Merged
nmayhall merged 2 commits into
v3-devfrom
trunc_fast
May 15, 2026
Merged

nmayhall merged 2 commits into
v3-devfrom
trunc_fast

Conversation

@nmayhall

Copy link
Copy Markdown
Owner

What

Type-parameterize CompositeTruncation's strategies field as a typed Tuple instead of Vector{TruncationStrategy}.

Why

The abstract Vector{TruncationStrategy} eltype prevents the JIT from specializing the per-element loop in _apply!(::CompositeTruncation). Each _apply!(O, strategy) call is a dynamic-dispatch boundary that prevents Julia from inlining the inner coeff_clip! / weight_clip! calls.

Switching to a typed Tuple{S1, S2, ...} field lets the compiler fully specialize the recursive tail-pop iteration in _apply!, inlining each strategy's filter loop into a single specialized truncate routine.

Measurement

@btime A/B on truncate!(rand(PauliSum{40}, n_paulis=100000), composite) where composite = CompositeTruncation(CoeffTruncation(0.1), WeightTruncation(4)):

  • Old (Vector field): baseline
  • New (Tuple field): ~8-9× faster

Public API

Surface Status
Variadic CompositeTruncation(s::TruncationStrategy...) unchanged
AbstractVector{<:TruncationStrategy} constructor added (converts to tuple internally)
Reading .strategies now returns Tuple instead of Vector
Mutating .strategies (push!/pop!) breaking — tuples are immutable

The mutating-field break is the only behavioral change. I don't think any caller in this repo (or in the few downstream users I'm aware of) does that, but worth flagging.

Tests

test/test_truncation.jl updated to assert the new tuple field type. All 9075 tests pass.

nmayhall-vt and others added 2 commits May 15, 2026 00:27
… a tuple

Storing strategies in a Vector{TruncationStrategy} (abstract eltype)
means the per-element loop in _apply!(::CompositeTruncation) is a
dynamic-dispatch boundary that prevents Julia from inlining the inner
coeff_clip! / weight_clip! calls into the outer truncate path.

Switching to a typed Tuple{S1, S2, ...} field lets the compiler fully
specialize the recursive tail-pop iteration in _apply!, inlining each
strategy filter loop into a single specialized truncate routine.

Measured on truncate!(rand(PauliSum{40}, n_paulis=100000), composite)
where composite = CompositeTruncation(CoeffTruncation, WeightTruncation):
~8-9x speedup (per @Btime A/B). End-to-end downstream demos see
comparable wall-time reductions on hot truncation paths.

Public API preserved:
- Variadic CompositeTruncation(s::TruncationStrategy...) unchanged.
- AbstractVector constructor added for convenience (converts to tuple).
- Field access .strategies returns a Tuple instead of a Vector;
  callers that mutated this field (push!/pop!) would break, but reading
  it and constructing via the variadic form are unchanged.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@nmayhall
nmayhall merged commit 8f811f3 into v3-dev May 15, 2026
5 checks passed
@codecov-commenter

Copy link
Copy Markdown

Welcome to Codecov 🎉

Once you merge this PR into your default branch, you're all set! Codecov will compare coverage reports and display results in all future pull requests.

Thanks for integrating Codecov - We've got you covered ☂️

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.

3 participants