Repository navigation
Conversation
`planartrace!` now precomputes the subblock positions and recoupling
coefficients in a cached `TraceTransformer`, and executes them with a
sector-independent kernel, analogous to the index manipulations. This
replaces the per-tree loop that built ad-hoc single-pair `FusionTreeBlock`s.
- `planar_trace` is defined for `Union{FusionTreePair, FusionTreeBlock}`,
with unique-fusion pairs returning `dst => coeff` and blocks `dst => U`,
and throws when the traced sectors are not dual to each other
- the transformer skips such (sub)blocks upfront and groups the data by
destination, such that every destination subblock is written once and
`β` is handled inside the kernel
- blocks with several destination trees are traced (and permuted) into a
buffer, recoupled with a single matmul and added into the destination
- `FusionTreeBlock`s hash their uncoupled sectors and duality flags
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
GPU tensors pack the `TraceTransformer` into `isbits` descriptors, cached per device storagetype, and trace with one thread per destination element, fusing the sum over the traced entries and the recoupling into a single kernel, analogous to the generic tree transformers. Other tensor types, such as adjoints, are first converted to `TensorMap`s: tracing subblock views with cuTENSOR fails for data offsets that are not aligned (e.g. `Float64` data at odd offsets). `_linear_index` is now written as an explicit loop, since `sum` of an empty tuple, as occurs for a full trace, does not compile for GPUs. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The first stage sums chunks of at most `max(256, √ntraced)` traced entries per thread, so full reductions and traces with few remaining entries are still spread over many threads. The second stage recouples these partials with one thread per destination element, such that traced entries are summed once per source rather than once per destination tree. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This replaces the per-tree loop in
planartrace!, which used the fusion tree internals through ad-hoc single-pairFusionTreeBlocks, with the same precompute/execute split as the index manipulations (treetransformers.jl/indexmanipulations.jl).Fusion trees
planar_trace(src::Union{FusionTreePair, FusionTreeBlock}, p, q)follows the conventions oftranspose/repartition: unique-fusion pairs map todst => coeff, blocks todst => Uwith a dense recoupling matrix. It repartitions all legs to the outgoing side, traces the splitting trees into the full block of remaining trees, and transposes that block.trace_sectors_matchinstead, which in the generic case avoids computing repartitions/transposes of blocks that vanish anyway.FusionTreeBlocks now hash their uncoupled sectors and duality flags, since the ad-hoc single-pair blocks are gone.Precompute:
TraceTransformer@cached treetracer(A, Vdst, Vsrc, p, q), keyed on the destination storagetype like the other transformers.(U, inds_dst, inds_src)entries, grouped by destination block: several source blocks (one per traced sector) contribute to the same destination. Every destination subblock appears in exactly one entry, so threaded tasks never write the same subblock, and subblocks without contributions get an entry that only scales byβ.Execute:
trace_transform_kernel!add_transform_kernel!, including the per-task workspaces.βon the first contribution._recouple!), and add into the destinations.GPU kernel
GPU tensors pack the
TraceTransformerintoisbitsdescriptors (cached per device storagetype, like the braid/transpose transformers) and trace in two stages:max(256, √ntraced)traced entries (one summed stride per traced pair) into a scratch buffer fromallocator, so full reductions and traces with few remaining entries are still spread over many threads;Other tensor types (e.g. adjoints) are converted to
TensorMaps first. Tracing subblock views with cuTENSOR, as the previous implementation did for all GPU tensors, fails withCUDA error: misaligned addressfor data at unaligned offsets (reproduced forFloat64fℤ₂ ⊠ SU₂ data)._linear_indexis now an explicit loop, sincesum(())(a full trace) does not compile for GPUs.Tested on an RTX A6000 against the CPU results for the same sectors and traces, in
Float64andComplexF64, including adjoint sources,β = 0with NaN-filled output, and full traces split into several chunks.test/cuda/planar.jlgains a symmetricplanartracetest for every space in the spacelist and for large traces;cuda/planarandcuda/tensorspass locally.GPU timings for one-stage (one thread per destination element) vs. two-stage kernel, for degeneracies 40 (fℤ₂), 30 (Fibonacci), 12/10/8 (fℤ₂ ⊠ SU₂):
Testing
tensors/planar,tensors/contractionsandsymmetries/doubletreepass locally; the planar trace test indoubletree.jlnow uses the block method for generic fusion.Not covered: JET was not run locally (it passes in CI); the GPU kernels were only tested on CUDA, not AMDGPU.
🤖 Generated with Claude Code