A from-scratch ML framework in C++20 with a PyTorch-like Python API.
- Automatic differentiation -- reverse-mode autograd with gradient checking on every op
- Strided tensor engine -- zero-copy views, NumPy interop
- Hand-written AVX2 SIMD matmul -- ~8x faster than naive on x86
- Full transformer stack -- multi-head attention, LayerNorm, GELU, GPT
- CUDA backend -- optional GPU kernels (
--device cudain Python,-DTIRAMISU_ENABLE_CUDA=ONin CMake) - PyTorch-familiar API --
Tensor,requires_grad,backward(),nn.Linear,optim.Adam
pip install tiramisu-mlRequires Python 3.10+. Wheels ship for Linux (x86_64, aarch64), macOS (x86_64, arm64), and Windows (amd64); other platforms build from sdist and need CMake + a C++20 compiler.
import numpy as np
import tiramisu as tr
# Random batch of 32 samples, 10 features, 3 classes
x = tr.from_numpy(np.random.randn(32, 10).astype(np.float32))
targets = tr.from_numpy(np.random.randint(0, 3, size=(32,)).astype(np.float32))
layer1 = tr.nn.Linear(10, 64)
layer2 = tr.nn.Linear(64, 3)
# Forward pass
h = tr.relu(layer1.forward(x))
logits = layer2.forward(h)
loss = tr.nn.cross_entropy_loss(logits, targets)
# Backward pass
loss.backward()
# Optimize
params = layer1.parameters() + layer2.parameters()
optimizer = tr.optim.Adam(params, lr=1e-3)
optimizer.step()
optimizer.zero_grad()import numpy as np
import tiramisu as tr
# Creation
tr.Tensor([2, 3]) # zero-filled float32
tr.from_numpy(np.zeros((2, 3), np.float32))
# Arithmetic (with autograd)
tr.add(a, b) tr.add(a, 2.0) # addition
tr.sub(a, b) # subtraction
tr.mul(a, b) tr.mul(a, 2.0) # multiplication
tr.div(a, b) # division
tr.neg(a) # negation
# Activations
tr.relu(a) tr.gelu(a) # ReLU, GELU
tr.softmax(a) # softmax
# Reductions
tr.sum(a) tr.mean(a) # sum / mean over all elements
# Layout
a.reshape([6]) # reshape
tr.transpose(a, 0, 1) # swap dims 0 and 1
a.contiguous() # ensure contiguous memory
# Linear algebra
tr.matmul(a, b) # matrix multiplication
# Autograd
x = tr.from_numpy(np.array([2.0], np.float32))
x.requires_grad = True
y = tr.mul(x, x)
y.backward()
x.grad # gradient tensor
# NumPy interop
arr = np.asarray(a) # zero-copy when contiguous
a.numpy() # same, via methodimport tiramisu as tr
linear = tr.nn.Linear(in_features=784, out_features=10)
layernorm = tr.nn.LayerNorm(features=128)
gpt = tr.nn.GPT(
vocab_size=65,
d_model=128,
num_heads=4,
num_layers=2,
max_seq_len=256,
)
out = linear.forward(x)
params = gpt.parameters()
cfg = gpt.config()import tiramisu as tr
loss = tr.nn.cross_entropy_loss(logits, targets)
sm = tr.softmax(logits)
g = tr.gelu(x)import tiramisu as tr
optimizer = tr.optim.Adam(parameters, lr=1e-3)
optimizer = tr.optim.AdamW(parameters, lr=3e-4, weight_decay=0.1)
optimizer = tr.optim.SGD(parameters, lr=0.01)
optimizer.step()
optimizer.zero_grad()
tr.optim.clip_grad_norm_(parameters, max_norm=1.0)
scheduler = tr.optim.CosineAnnealingLR(base_lr=3e-4, total_steps=1000)
lr = scheduler.step()import tiramisu as tr
tr.serialize.save_gpt("model.ckpt", model, step=100, epoch=1)
step, epoch = tr.serialize.load_gpt("model.ckpt", model)import tiramisu as tr
tr.cuda_available() # True if built with CUDA
x = tr.from_numpy(arr, device="cuda") # place tensor on GPU
loss.cpu().numpy() # move back to CPU for NumPyToken indices are stored as float32 tensors today (the C++ embedding path reads float indices).
Python API (tiramisu)
│
└─→ pybind11 (_C)
│
├─→ core/ Tensor, Storage, dtype, device
├─→ ops/ CPU kernels (AVX2); optional CUDA
├─→ autograd/ backward tape, gradcheck
├─→ nn/ Linear, GPT, LayerNorm, loss
└─→ optim/ Adam, AdamW, SGD, schedulers
Runnable scripts live in examples/python/ and examples/ (C++).
| Script | Description |
|---|---|
examples/python/autograd_demo.py |
Minimal autograd: y = x² + 3x |
examples/python/linear_forward.py |
Forward pass + NumPy interop |
examples/python/train_mnist.py |
2-layer MLP on MNIST |
examples/python/gpt_step.py |
Single GPT training step |
examples/python/train_shakespeare.py |
Char-level GPT on Tiny Shakespeare |
# Python (after pip install)
python examples/python/train_mnist.py --data-dir data --epochs 5
python examples/python/train_shakespeare.py --preset tiny --epochs 3C++ examples require a local build (see below):
cmake --build build --target mnist && ./build/examples/mnist
cmake --build build --target train_shakespeare
./build/examples/train_shakespeare --preset tiny --epochs 3Only needed for C++ development, CUDA, or contributing. Requires CMake 3.20+ and a C++20 compiler.
cmake -S . -B build -G Ninja -DCMAKE_BUILD_TYPE=Release
cmake --build build --parallel
ctest --test-dir build --output-on-failureCUDA: add -DTIRAMISU_ENABLE_CUDA=ON. Debug builds enable ASan + UBSan by default (TIRAMISU_ENABLE_SANITIZERS=ON).
Python editable install from the repo root:
pip install -e ".[dev]"
pytest tests/python -vSee python/README.md for CMake Python extension build notes.
MIT
