Skip to content

Latest commit

History

60 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

ferrograd

A from-scratch tensor compiler in Rust, inspired by tinygrad.

Architecture

Follows the same pipeline as tinygrad, simplified:

Tensor API → Lazy UOp Graph → Scheduling → Codegen → Compilation → Execution

Each layer is a standalone module you can study independently:

ModuleWhat it doesCompiler concept
tensorLazy tensor API with kernel fusionLazy evaluation, scheduling
uopDAG-based IR with hash-consingIntermediate representations
scheduleLazy graph → proto-kernels + rangeifyScheduling, lowering
optimizeSymbolic simplification, upcast, unrollCompiler optimizations
codegenUOp graph → C sourceCode emission
gradientReverse-mode autograd as graph transformsAutomatic differentiation
rewriteFixed-point graph simplificationTerm rewriting
nnLinear layers and loss functionsNeural network primitives
dtypeData types bridging Rust, IR, and CType systems
deviceBuffer, Device trait, CPU backendHardware abstraction
shapeShape metadata and transformationsTensor algebra
datasetMNIST with auto-download and cachingData loading

Example

Train a two-layer MLP on MNIST from scratch:

use ferrograd::dataset::MNISTDataset;use ferrograd::nn::{Linear,Parameters};use ferrograd::optim::Sgd;use ferrograd::tensor::{cpu,Tensor};// Define a modelstructMlp{l1:Linear,l2:Linear}implMlp{fnforward(&self,x:&Tensor) -> Tensor{let h = self.l1.forward(x).relu();self.l2.forward(&h)}}implParametersforMlp{fnparameters(&self) -> Vec<Tensor>{[self.l1.parameters(),self.l2.parameters()].concat()}}// Trainlet dataset = MNISTDataset::load().unwrap();let model = Mlp{l1:Linear::new(784,128),l2:Linear::new(128,10)};let optim = Sgd::new(model.parameters(),0.01);let batch_x = dataset.train_images.narrow(0,0,256);let batch_t = one_hot(&dataset.train_labels[..256],10);let loss = model.forward(&batch_x).cross_entropy(&batch_t);
loss.backward();// reverse-mode autograd
optim.step();// SGD update

Everything is lazy — forward, cross_entropy, and backward just build a graph. optim.step() fuses it into kernels, compiles C via clang, and executes.

cargo run --example mnist --release # full training loop
DEBUG=4 cargo run --example demo # see generated C source

Status

The compiler pipeline is functional end-to-end: lazy tensor graphs, multi-kernel scheduling, reverse-mode autograd, and CPU code generation via clang. The MNIST example trains a small MLP from scratch.

Building

cargo clippy # build + lint (clippy pedantic is on)
cargo test# run all tests

License

MIT

About

A from-scratch tensor compiler in Rust

Resources

Stars

0 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages