Skip to main content

A lightweight C/CUDA tensor library with Python bindings

Project description

plast

a high-performance deep learning engine from scratch in C and CUDA.

zero dependencies. full autograd. tiled Ampere-optimized CUDA kernels. arena-allocated memory.

neural networks are data transformation pipelines. plast treats them that way.

philosophy

most frameworks model a network as a tree of objects. nn.Module subclasses, forward() methods, parameter registries — a leaky OOP abstraction over what is fundamentally a dataflow graph.

plast has that too (see classic api). but the real path is the functional pipeline:

input → normalize → relu → matmul(W1) → relu → matmul(W2) → softmax → loss

each stage is a pure function over tensors. compose them lazily. the scheduler sees the whole graph and JIT-compiles fused kernels for it. no python overhead between layers. no kernel launch overhead between fusable ops.

zero-cost abstractions are a compiler problem, not an API problem.

quickstart

git clone https://github.com/Vixel2006/plast.git
cd plast
pip install -e . --no-build-isolation
import plast as p
from plast.experiment import ExperimentConfig, ExperimentTracker

# functional pipeline — the pro path
def model(x, W1, b1, W2, b2):
    return x @ W1 + b1 |> p.nn.functional.relu |> p.nn.functional.linear(W2, b2)

# or the classic api — for noobs
net = p.nn.Sequential(
    p.nn.Linear(784, 256),
    p.nn.ReLU(),
    p.nn.Linear(256, 10),
)

architecture

plast uses a clean layered design. the scheduler orchestrates a DAG of tensor ops and dispatches to hardware-specific backends. a JIT compiler fuses adjacent ops into single CUDA kernels where possible.

                        [ Python API ]
                              │
                              ▼
                    ┌─────────────────────┐
                    │   pipeline composer │  ← functional pipelines, lazy graphs
                    │   (plast/pipeline/) │
                    └──────────┬──────────┘
                               │
                    ┌──────────┴──────────┐
                    │   scheduler + JIT   │  ← graph fusion, kernel compilation
                    │   (src/scheduler/)  │
                    └──────────┬──────────┘
                               │
                    ┌──────────┴──────────┐
                    │   tensor / memory   │  ← arena allocator, stride-aware views
                    │   (src/tensor/)     │
                    └──────────┬──────────┘
                               │
                    ┌──────────┴──────────┐
                    │   hardware backends │  ← abstract op dispatch
                    │   (src/backend/)    │
                    └──────────┬──────────┘
                               │
                   ┌───────────┴───────────┐
                   ▼                       ▼
            ┌──────────────┐      ┌──────────────┐
            │cuda kernels  │      │  cpu / simd  │
            │  sm_80+      │      │  avx+omp     │
            └──────────────┘      └──────────────┘

features

module what it does
autograd dynamic DAG with topological sort, correct gradient accumulation for reused nodes
tensor n-dimensional strided tensors, broadcasting, views without data copy
cuda kernels sm_80-optimized tiled matmul (32×32), fused element-wise, warp-level reductions, im2col conv2d
jit compiler (in development) runtime CUDA kernel fusion via NVRTC — fuses adjacent ops into single launch
scheduler DAG-graph traversal with integrated JIT — whole-pipeline fusion planning
functional pipeline lazy data-transformation composition `a
classic api nn.Module, nn.Sequential, optimizers, dataloaders — pytorch-compatible ergonomics
arena allocator pre-allocates full graph memory. zero malloc/free during training. deterministic lifetime
experiment tracking versioned runs, YAML configs/metrics, automatic checkpointing, best-run aggregation

experiment tracking

experiments are first-class citizens. each run is auto-versioned under experiments/{name}/run_{NNN}/:

config = ExperimentConfig(
    name="mlp_mnist",
    model={"hidden": 256, "dropout": 0.2},
    training={"lr": 1e-3, "epochs": 50},
    device="cuda",
)
tracker = ExperimentTracker(config)

for epoch in range(50):
    loss = train_epoch(model, data)
    tracker.log_epoch(epoch, {"train_loss": loss})

tracker.finish()

produces:

experiments/mlp_mnist/
├── summary.yaml            ← best run across all runs
├── run_001/
│   ├── config.yaml         ← frozen config
│   ├── metrics.yaml        ← per-epoch metrics
│   └── checkpoints/
│       └── best_model.npz  ← best weights
├── run_002/
│   └── ...

the pipeline approach (vs oop modules)

the classic nn.Module API exists and works. it's fine for quick experiments and for people who think in layers.

the functional pipeline is different. you define your forward pass as a composition of pure tensor functions:

from plast.pipeline import pipe

forward = pipe(
    lambda x: p.nn.functional.linear(x, W1, b1),
    p.nn.functional.relu,
    lambda x: p.nn.functional.linear(x, W2, b2),
    p.nn.functional.softmax,
)

the pipe object is lazy. nothing executes until you call it. the scheduler intercepts the composition, builds a DAG, and hands it to the JIT compiler. fusable ops are merged into a single CUDA kernel. non-contiguous data is packed once. the arena is pre-sized for the exact pipeline shape.

what you get:

  • fused kernels — relu + matmul becomes one launch instead of two
  • lazy allocation — arena sized from the static graph, not on every forward()
  • zero python overhead — the entire pipeline runs through compiled code once the graph is built

cuda kernels

all kernels target sm_80 (Ampere) and above. currently shipping:

kernel approach status
matmul tiled 32×32, shared memory, NT/TN variants, batch support done
conv2d im2col + matmul, col2im backward done
element-wise contiguous fast path + broadcast fallback, fused variants planned done
reductions warp-level tree reduction, shared-memory dim reduction done
optimizers SGD, Adam, AdamW fused kernels done

c api

plast is a C library first. the python bindings are a thin pybind11 layer. if you want to embed the engine in a C or C++ project:

#include "arena.h"
#include "tensor.h"
#include "graph.h"

Arena arena = arena_create(1024 * 1024 * 1024, DEVICE_CUDA);
Tensor* x = tensor_create(&arena, shape, 2, FLOAT);
Tensor* y = tensor_create(&arena, shape_out, 2, FLOAT);
Node*  n = matmul_node(&arena, x, y, NULL);
forward(n);
backward(n);
arena_release(&arena);

roadmap

  • Optimizing CUDA Kernels — Optimizing our slow cuda kernels
  • JIT compiler — NVRTC-based kernel fusion in the scheduler
  • fused ops — matmul+relu, conv+bn+relu as single kernels
  • functional pipeline builderpipe() API with lazy DAG construction
  • mixed precision — FP16/BF16 on tensor cores
  • distributed — MPI + NCCL for multi-GPU training
  • python bindings for pipeline — bring the pro path to python

contributing

prs welcome. keep it zero-dependency. keep it fast.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pyplast-0.1.1.tar.gz (61.0 kB view details)

Uploaded Source

File details

Details for the file pyplast-0.1.1.tar.gz.

File metadata

  • Download URL: pyplast-0.1.1.tar.gz
  • Upload date:
  • Size: 61.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.10.7 {"installer":{"name":"uv","version":"0.10.7","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Arch Linux","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for pyplast-0.1.1.tar.gz
Algorithm Hash digest
SHA256 f4887f1bc6fe07232a7994273719490ff6cadbba079567557aaf8a0e7c48f627
MD5 df4890b90a3fccce6b24777ff692500f
BLAKE2b-256 a643447ba9b2b99385cffd5032b441c0568718040d7d3a5eafe8d5c5959414c6

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page