Papers
Topics
Authors
Recent
Search
2000 character limit reached

Tensor-Oriented Metaprogramming (TOM)

Updated 6 July 2026
  • TOM is a framework that transforms tensor programs into a specialized IR ensuring efficient, purely functional differentiation based on the Cheap Gradients Principle.
  • It avoids mutation and implicit sparsity by encoding explicit sparsity through indicator predicates and Tensor SSA, streamlining AD transformations.
  • Its systematic IR-to-IR rewrites guarantee reverse-mode AD within provable cost bounds, enabling robust optimization and parallel scheduling.

Searching arXiv for the specified paper to ground the article and confirm bibliographic details. Tensor-Oriented Metaprogramming (TOM) denotes, in the design perspective developed from "Differentiating a Tensor Language," a language/intermediate-representation and compilation framework for tensor programs with strong differentiation and performance guarantees. Its defining objective is to compile derivatives of tensor programs into code that is both purely functional and provably efficient relative to the original program, thereby extending the Cheap Gradients Principle to tensor programs with variable-sized data while avoiding mutation, aliasing, and dependence on unpredictable algebraic simplification (Bernstein et al., 2020).

1. Problem setting and the Cheap Gradients Principle

The central problem is to compile derivatives of tensor programs into code that is purely functional and provably efficient relative to the original program. In the formulation adopted here, the relevant efficiency criterion is the Cheap Gradients Principle: for a function ff, the reverse-mode gradient DTf\mathbf{D^T} f can be evaluated in time at most a constant factor of the cost of evaluating ff, under a cost model counting scalar arithmetic operations. Formally, the principle is expressed as

cost(DTf)Ccost(f)\text{cost}(\mathbf{D^T} f) \le C \cdot \text{cost}(f)

for some constant CC, often C4C \approx 4 in the scalar model discussed in the source material (Bernstein et al., 2020).

The motivation for TOM arises from the observation that naively differentiating tensor code, as done in systems such as TensorFlow and PyTorch, can cause asymptotic slowdowns in pathological cases. The supplied examples are structurally important. For

let A=diag(x) in trace(A)++trace(A),\text{let } A = \text{diag}(x) \text{ in } \text{trace}(A) + \cdots + \text{trace}(A),

with xx of length NN and kk traces summed, the primal cost is DTf\mathbf{D^T} f0, because diag(x) materializes an DTf\mathbf{D^T} f1 matrix and each trace costs DTf\mathbf{D^T} f2. By contrast, the gradient with respect to DTf\mathbf{D^T} f3 can naively cost DTf\mathbf{D^T} f4, since each adjoint trace produces a dense matrix with mostly zero off-diagonal entries. The ratio

DTf\mathbf{D^T} f5

violates Cheap Gradients.

A second example uses

DTf\mathbf{D^T} f6

The source states that XLA compiles the primal to DTf\mathbf{D^T} f7 by recognizing that only the first row and column of the diagonal matrix are used, but that XLA’s autogenerated gradient runs in DTf\mathbf{D^T} f8. These examples establish the basic design requirement for TOM: differentiation should satisfy a provable complexity relation to the primal program, rather than relying on optimizer luck.

2. Core tensor language as TOM’s analyzable IR

The prototype core for TOM is a small Tensor Language intended as a compact, analyzable IR for tensor programs. Its types are scalars DTf\mathbf{D^T} f9, pairs ff0, and arrays ff1, with multidimensional tensors represented by nesting such as ff2 (Bernstein et al., 2020).

The expression language includes variables ff3, scalar constants ff4, scalar arithmetic ff5 and ff6, scalar black-box primitives ff7, pairs ff8 with projections ff9 and cost(DTf)Ccost(f)\text{cost}(\mathbf{D^T} f) \le C \cdot \text{cost}(f)0, tensor generation

cost(DTf)Ccost(f)\text{cost}(\mathbf{D^T} f) \le C \cdot \text{cost}(f)1

tensor summation

cost(DTf)Ccost(f)\text{cost}(\mathbf{D^T} f) \le C \cdot \text{cost}(f)2

indexing cost(DTf)Ccost(f)\text{cost}(\mathbf{D^T} f) \le C \cdot \text{cost}(f)3, indicator expressions cost(DTf)Ccost(f)\text{cost}(\mathbf{D^T} f) \le C \cdot \text{cost}(f)4, and let-bindings cost(DTf)Ccost(f)\text{cost}(\mathbf{D^T} f) \le C \cdot \text{cost}(f)5. Predicates include arithmetic comparisons on indices, Boolean connectives, bounded existential quantification cost(DTf)Ccost(f)\text{cost}(\mathbf{D^T} f) \le C \cdot \text{cost}(f)6, and relation predicates cost(DTf)Ccost(f)\text{cost}(\mathbf{D^T} f) \le C \cdot \text{cost}(f)7 for data-dependent sparsity. Index expressions include index variables, size variables, integer constants, and affine index arithmetic.

Its semantics are defined in big-step style with an environment cost(DTf)Ccost(f)\text{cost}(\mathbf{D^T} f) \le C \cdot \text{cost}(f)8. The key constructs are comprehension-like. The generator cost(DTf)Ccost(f)\text{cost}(\mathbf{D^T} f) \le C \cdot \text{cost}(f)9 evaluates CC0 for each CC1; the reduction CC2 evaluates the scalar sum over that range; and the indicator

CC3

generalizes Iverson’s bracket to any type CC4.

This language is purely functional, array- and comprehension-based, and closed under composition. In the TOM interpretation, those properties are not merely presentational. They imply that tensor structure is represented explicitly by CC5, CC6, and CC7, while scalar computation remains separate. A plausible implication is that this separation makes the IR particularly suitable for equational rewrites, AD transforms, and backend lowering.

3. Indicators, explicit sparsity, and the avoidance of mutation

A central idea in the TOM design is that sparsity should be explicit in the IR rather than implicit in a pattern of mutating writes. The indicator function from Iverson’s APL provides the mechanism. In scalar form,

CC8

and in the tensor language it is generalized to typed zero, so that CC9 is either C4C \approx 40 or the zero of C4C \approx 41’s type (Bernstein et al., 2020).

The supplied examples show why this matters for differentiation. For a sum that accesses only selected entries of an array, a naive adjoint can appear to require many separate generated arrays whose combination suggests C4C \approx 42 additions. If the indicators are retained and rewritten appropriately, the result becomes a single generated vector with zero entries where the predicate fails, reducing the work to C4C \approx 43. The same structural issue appears in the trace and eye constructions: C4C \approx 44 Their derivatives are naturally sparse because only diagonal positions matter.

Traditional reverse-mode AD in tensor frameworks uses in-place accumulation into dense arrays via +=. In the source description, sparsity is then implicit in which elements are touched and which remain zero. This is impure, relies on mutation and aliasing, and complicates downstream optimization and parallelization. The TOM approach instead encodes sparsity through indicator predicates and treats all accumulation as ordinary expressions. The cost model discounts additions of zero and summations with zero or one nonzero term. This yields a purely functional representation of reverse-mode computation in which no shared gradient buffer is updated destructively.

This suggests a general TOM principle: structural sparsity, including diagonals, bandedness, masked operations, and similar patterns, should be represented at the IR level rather than hidden inside opaque primitives or imperative accumulation logic.

4. Tensor SSA normal form

To support systematic reasoning and transformation, the paper introduces Tensor SSA, a normal form analogous to SSA but tailored to tensor computations. Statements are sequences of let-bindings ending in an output, and expressions are restricted to regular tensor forms such as input projections, constants, tensor-wise addition, tensor-wise scalar function application, and tensor contractions expressed through generators, summations, and predicates (Bernstein et al., 2020).

In the simplified grammar given in the source, Tensor SSA includes forms such as

C4C \approx 45

C4C \approx 46

C4C \approx 47

and contraction nodes in which predicates C4C \approx 48 encode index relations, sparsity, and contraction structure. Each SSA variable is assigned once, and higher-level structure is flattened so that shapes and access patterns are visible in the IR.

Normalization into Tensor SSA proceeds by a sequence of cost-non-increasing passes. Let-lifting moves nested let bindings to the top level, yielding a block-with-return structure. Pair elimination uses the type isomorphism

C4C \approx 49

to ensure that only inputs and outputs remain paired, while intermediates are scalars or arrays in struct-of-arrays form. Gen-pushout pushes let A=diag(x) in trace(A)++trace(A),\text{let } A = \text{diag}(x) \text{ in } \text{trace}(A) + \cdots + \text{trace}(A),0 outward and indicators inward, with rewrites such as

let A=diag(x) in trace(A)++trace(A),\text{let } A = \text{diag}(x) \text{ in } \text{trace}(A) + \cdots + \text{trace}(A),1

SSA conversion then assigns fresh variables to subexpressions, recognizes instances of the core grammar, and applies structural common subexpression elimination together with canonicalization of predicates and index lists.

Tensor SSA is valuable because it separates structure from computation, localizes scalar cost to the bodies of generators and contractions, and provides a regular substrate for fusion, tiling, algebraic rewrites, and parallel scheduling. In the TOM formulation, it functions as the canonical IR to which frontends lower, on which AD is defined, and over which optimization passes operate.

5. Reverse-mode AD from the universal property of inner products

The derivation of reverse-mode AD is not presented as an imperative tape algorithm but as a syntactic transformation justified by adjointness with respect to an inner product. For let A=diag(x) in trace(A)++trace(A),\text{let } A = \text{diag}(x) \text{ in } \text{trace}(A) + \cdots + \text{trace}(A),2, the forward derivative let A=diag(x) in trace(A)++trace(A),\text{let } A = \text{diag}(x) \text{ in } \text{trace}(A) + \cdots + \text{trace}(A),3 is characterized by

let A=diag(x) in trace(A)++trace(A),\text{let } A = \text{diag}(x) \text{ in } \text{trace}(A) + \cdots + \text{trace}(A),4

and in coordinates

let A=diag(x) in trace(A)++trace(A),\text{let } A = \text{diag}(x) \text{ in } \text{trace}(A) + \cdots + \text{trace}(A),5

Within the language, the forward derivative is the transform let A=diag(x) in trace(A)++trace(A),\text{let } A = \text{diag}(x) \text{ in } \text{trace}(A) + \cdots + \text{trace}(A),6, where let A=diag(x) in trace(A)++trace(A),\text{let } A = \text{diag}(x) \text{ in } \text{trace}(A) + \cdots + \text{trace}(A),7 maps primal variables to differential variables. The source gives standard rules for variables, addition, products, scalar black-box functions, generators, summations, and let-bindings; the let rule is explicitly identified as the chain rule over a let-binding (Bernstein et al., 2020).

The adjoint derivative let A=diag(x) in trace(A)++trace(A),\text{let } A = \text{diag}(x) \text{ in } \text{trace}(A) + \cdots + \text{trace}(A),8 is characterized by the inner-product identity

let A=diag(x) in trace(A)++trace(A),\text{let } A = \text{diag}(x) \text{ in } \text{trace}(A) + \cdots + \text{trace}(A),9

To internalize this construction, the language is extended with inner product expressions. The source lists scalar inner products xx0, pair inner products, and array inner products of the form

xx1

An annotated program places primal lets, their differentials, and a final inner product in scope. Rewrite rules then push the inner product backward through the program, transforming xx2 into xx3.

The mechanical rules unpack and reorder lets, decompose and recombine pairs, reverse lets in reverse-mode fashion, split contributions across additions, invoke primitive reverse rules for scalar black-box functions, and transform tensor contractions by manipulating predicates so that the induced sparsity remains explicit. The source emphasizes three consequences: the construction is correct by construction because every rewrite is justified by the inner-product identity; it avoids mutation entirely; and it is generic in the sense that it applies to any Tensor SSA program rather than to a fixed library of handwritten gradient kernels.

For TOM, reverse-mode AD is therefore an IR-to-IR rewrite system over Tensor SSA. A plausible implication is that primal and adjoint programs can share the same downstream optimizer pipeline because they inhabit the same purely functional representation.

6. Cost model, complexity guarantees, examples, and system-level implications

The complexity claims are formulated relative to a cost model that counts scalar additions, multiplications, and black-box scalar operations, but does not count index arithmetic or memory operations. Addition is treated specially in the presence of indicators: for

xx4

the extra unit cost of addition is charged only when both predicates hold. Summation is also indicator-aware: summing xx5 nonzero terms costs xx6 additions, while summing zero or one term has no arithmetic overhead. The source states that this design captures the true cost of arithmetic when sparsity allows elimination of operations and is compatible with an ideal compilation that can exploit indicator-based sparsity (Bernstein et al., 2020).

Two principal complexity theorems are given. For forward mode, Theorem 4.1 states that for xx7 in Tensor SSA,

xx8

For reverse mode, with input type xx9, output type NN0, and NN1 denoting the size of type NN2, define

NN3

Then the adjoint transform satisfies

NN4

These results constitute the Cheap Gradients Principle for the tensor language in question.

The examples supplied in the source show how these abstractions operate concretely. For one-dimensional convolution

NN5

the forward derivative is

NN6

and the adjoint is

NN7

The source identifies this as the correlation operation, showing that a contraction node in Tensor SSA can be reversed into another contraction node without resorting to in-place accumulation. For the loss

NN8

the gradient is expressed by first defining

NN9

and then using the adjoint convolution form

kk0

The role of let-lifting is explicit in the batched case: it moves nested definitions outward so the result becomes a batched contraction amenable to recognition by subsequent optimization passes.

The trace and eye example further clarifies the interaction between primitive cost and composite cost: kk1 The source lists the adjoints

kk2

Naively, eye appears to cost kk3 in a purely functional setting, but the indicator-aware cost model does not charge for known-zero structure under suitable compilation strategies. The source therefore emphasizes that one must reason about composite operations and their sparse structure, not only about isolated primitives.

At the systems level, TOM is contrasted with TensorFlow, PyTorch, and JAX. The distinction is not that those systems lack tensor abstractions, but that they typically define AD at the level of coarse primitives and frequently rely on mutation for gradient accumulation, whereas TOM adopts a small compositional array IR with kk4, kk5, kk6, and Tensor SSA, and defines AD as a syntactic transformation over that IR. The source further states that TOM could lower dense cases to loop-based code or polyhedral techniques and sparse cases to libraries such as TACO or code similar to TACO generated from indicator predicates. This suggests a framework in which optimization, scheduling, sparse lowering, and formal verification all operate on the same pure representation.

In that sense, TOM is not merely a notation for tensor expressions. It is a metaprogramming architecture organized around four commitments: a small functional tensor IR, explicit representation of sparsity via indicators, reverse-mode AD derived from inner-product identities, and formal cost bounds that preserve Cheap Gradients for tensor programs with variable-sized data.

Definition Search Book Streamline Icon: https://streamlinehq.com
References (1)

Topic to Video (Beta)

No one has generated a video about this topic yet.

Whiteboard

No one has generated a whiteboard explanation for this topic yet.

Follow Topic

Get notified by email when new papers are published related to Tensor-Oriented Metaprogramming (TOM).