Feat: mosaic tpu tensor product#7
Merged
Merged
Conversation
armandpicard
approved these changes
Jul 3, 2026
Merged
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.
Adds forward and backward tensor product Pallas kernels for TPU.
Some context
The tensor product consists of a bilinear contraction of (x, y) with a sparse 3D array of coefficients (see core.TensorProduct):
where$c$ is passed in sparse COO format (Clebsch-Gordan coefficients) sorted lexicographically by output index first. Sparse e3j kernels therefore loop over coefficients to load $x_j$ and $y_k$ from buffers (here VMEM, 2-stage pipelining).
Baseline
In contrast the e3nn baseline uses a block-sparse for loop of dense einsums (see tensor_products.py)
Channel mixing
Each irreducible block (indexed by degree$l$ , of dimension $2l + 1$ ) has a multiplicity, typically an MLIP's number of channels (32, 64, 128...). Different implementations may use different layouts, i.e.
Layout.E3NN: the string"128x0e + 128x1o"denotes 128 scalars followed by 128 vectors (flattened)Layout.TRAILING_CHANNELS(our kernels): multiplicities are factored in a trailing channel axis, so"128x0e + 128x1o"is represented as (1+3, 128) shaped arrays.Layout.LEADING_CHANNELS: channel axis before the trailing feature axis, usually less efficient.The way channel contents are mixed only needs to be bilinear, there are otherwise no constraints coming from equivariance. The channel mixing mode thus depends on downstream settings:
TPMode.MAP: channel-wise bilinear couplings (x and y have equal channel dimensions)TPMode.OUTER: broadcast y with x along the channel axis (y has 1 channel) as a particularcase of
np.outer-like mixingTPMode.INNER: sum along the channel axis after the bilinear coupling (x and y have equal channel dimensions)Note: INNER is the dual of OUTER, which means it occurs during the backward pass of an outer coupling (leftout from this PR's forward kernel).
Benchmarks (TPUv4)
The forward and backward kernels reach near-HBM throughput: ~1 TB/s with 128 channels and
l_max=3, close to the 1.2 TB/s advertized IIUC.Forward:

Backward:

A follow up PR by @armandpicard should address the relative performance gap at low multiplicities by packing more copies in a single buffer.