可运行 API 例子¶
常规入口直接使用 torch.Tensor 和 PyTorch autograd。每节代码独立运行,通过断言给出结果,不依赖前一节变量。后面的原生 runtime 例子用于编译器与存储的高级场景,不是使用 MessagePassing 的前置要求。依赖与构建见快速上手。这些代码纳入文档执行测试,不只是伪代码。
| 任务 | API 契约 | 完整例子 |
|---|---|---|
| 默认 Torch 输入、输出与梯度 | Torch 接口契约 | 本页 Torch |
| Tensor、view、梯度 | 默认 Torch 接口 | 本页 Tensor |
| CSR 聚合 | Graph / MessagePassing | 本页 message passing |
| 预算、spill、持久化 | 执行与存储 | 本页存储 |
| 物理层搬运 | 编译器内存 | 本页物理实例 |
| 选择 backend、排错 | 执行指南 | 执行诊断代码 |
| IR 与生成代码 | IR 实例 | 完整阶段产物 |
| Reducer、自定义语义 | Reducer | 图算法例子 |
| Torch / NN 互操作 | 互操作 | Attention 例子 |
| 循环、隐式 VJP | 求解器 | 求解器例子 |
| 多进程与分页图 | 支持范围 | 分布式例子 |
默认入口:Torch 输入、输出与梯度¶
本例先单独安装 Torch,再安装 Tiga;CPU 即可运行,不需要 tg.from_torch 包装。
后面的原生存储/runtime 例子不要求 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.]))
该例验证数值与求导契约,不表示所有 provider 都生成了机器代码;实际执行路线见 kernel diagnostics。
Torch Tensor、view 与梯度¶
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 消息传递¶
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.]
存储与分配策略¶
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())
编译器物理实例往返¶
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"