Skip to content

Runnable API examples

Start with ordinary torch.Tensor inputs and PyTorch gradients. Each recipe runs independently; assertions specify results and no variables are borrowed from other sections. The later native-runtime recipes are advanced compiler/storage examples, not a prerequisite for MessagePassing. See getting started for installation. Documentation tests execute these recipes, not just syntax-check them.

Task Contract Complete example
Default Torch input/output and gradients Torch-facing contract Torch recipe
Tensor, views, gradients Default Torch interface Tensor recipe
CSR aggregation Graph / MessagePassing Message passing
Budgets, spill, persistence Execution and storage Storage
Physical transfers Compiler memory Physical instances
Backend selection and failures Execution guide Diagnostic code
IR and generated code IR walkthrough Stage artifacts
Reducers and semantics Reducers Graph algorithms
Torch / NN interop Interop Attention
Loops and implicit VJP Solvers Solver examples
Multiple processes and paged graphs Support status Distributed examples

Default: Torch inputs, outputs and gradients

Install Torch separately before Tiga for this recipe; no CUDA or tg.from_torch wrapper is needed. Native storage/runtime recipes do not require Torch.

import torch
import tiga as tg

class WeightedSum(tg.MessagePassing):
    reducer = tg.sum()
    def edge(self, src, dst, edge):
        return src.x * edge.w

graph = tg.Graph.from_csr(torch.tensor([0, 2, 3, 3]),
                          torch.tensor([0, 1, 1]), num_src=2, validate="full")
x = torch.tensor([2., 3.], requires_grad=True)
w = torch.tensor([4., 5., 2.], requires_grad=True)
out = WeightedSum()(graph=graph, src={"x": x}, dst={}, edge={"w": w})
assert isinstance(out, torch.Tensor)
torch.testing.assert_close(out, torch.tensor([23., 6., 0.]))
dx, dw = torch.autograd.grad(out.sum(), (x, w))
torch.testing.assert_close(dx, torch.tensor([4., 7.]))
torch.testing.assert_close(dw, torch.tensor([2., 3., 3.]))

This validates the public value/gradient contract, not a claim that every provider uses generated code. Inspect the kernel's diagnostics for the selected execution route.

Torch Tensor, views and gradients

import torch

x = torch.tensor([[1., 2.], [3., 4.]], requires_grad=True)
view = x.transpose(0, 1)
loss = (view * view).sum()
dx, = torch.autograd.grad(loss, x)
assert loss.tolist() == 30.
assert dx.tolist() == [[2., 4.], [6., 8.]]

CSR message passing

import torch
import tiga as tg

class WeightedSum(tg.MessagePassing):
    reducer = tg.sum()
    def edge(self, src, dst, edge):
        return src.x * edge.w

graph = tg.Graph.from_csr(torch.tensor([0, 2, 3], dtype=torch.int64),
                          torch.tensor([0, 1, 0], dtype=torch.int64), num_src=2)
x = torch.tensor([2., 3.], requires_grad=True)
w = torch.tensor([1., 2., 4.], requires_grad=True)
out = WeightedSum()(graph=graph, src={"x": x}, dst={}, edge={"w": w})
assert out.tolist() == [8., 8.]
assert torch.autograd.grad(out.sum(), x)[0].tolist() == [5., 2.]

Storage and allocation policy

from pathlib import Path
import tempfile

import tiga as tg

with tempfile.TemporaryDirectory(prefix="tiga-memory-example-") as directory:
    with tg.execution(memory={"host": "1MiB", "nvme": "1MiB"},
                      spill_dir=directory) as run:
        values = tg.tensor([float(i) for i in range(8)], requires_grad=True)
        loss = (values * values).sum()
        loss.spill()  # temporary residency; autograd history survives
        gradients = tg.autograd.grad(loss, values)
        assert gradients.tolist() == [float(2 * i) for i in range(8)]
        back = values.cpu()
        path = Path(directory) / "activations.tiga"
        tg.save(values, path)  # persistent value snapshot, not an eviction
        restored = tg.load(path)  # metadata only until first observation
        assert restored.tolist() == back.tolist()
        print(run.memory_report())

Compiler physical-instance round trip

import tiga as tg

with tg.runtime.HierarchyRuntime(budgets={"ram": 8, "nvme": 4}) as rt:
    source = rt.allocate("x", 0, tier="ram", capacity_bytes=4)
    source.buffer.write(b"tiga")
    page = rt.allocate("x", 0, tier="nvme", capacity_bytes=4)
    rt.transfer(source, page).wait()
    destination = rt.allocate("x", 0, tier="ram", capacity_bytes=4)
    rt.transfer(page, destination).wait()
    assert destination.buffer.read() == b"tiga"