tenferro

tenferro is a Rust-native tensor computation stack with opt-in autodiff for scientific workloads: typed tensors, dynamic tensors, PyTorch-style immediate execution with backward() and EagerRuntime functional grad, vjp, and jvp, JAX-style traced graphs, einsum, linear algebra, FFT, and explicit CPU, CUDA, and experimental WebGPU backend control.

The project covers both ordinary tensor computation and autodiff workflows. Start with the smallest API that solves your problem, then add autodiff, graph compilation, CUDA, or experimental WebGPU only when the workflow needs them.

tenferro-rs architecture overview

Where To Start

Workflow Start with
First setup and a checked CPU program Getting Started
Core terms and the three main choices Core Concepts
Step-by-step runnable examples Tutorials
Choosing between TypedTensor, Tensor, EagerTensor, and TracedTensor Choosing a Tensor API
Understanding direct, eager, and traced execution Execution Models
Column-major storage and row-major import/export Memory Order
CPU, CUDA, and experimental WebGPU backend behavior Devices and GPU
Static-shaped StableHLO and PJRT plugin loading XLA and PJRT
Runtime-dependent dimensions in traced graphs Dynamic and symbolic shapes
API documentation for every crate API Reference

First Direct Tensor Example

use tenferro_cpu::CpuBackend;
use tenferro_linalg::LinalgBackend;
use tenferro_runtime::{TensorView, TypedTensor, TypedTensorOpsExt};

fn assert_close(actual: &[f64], expected: &[f64]) {
    assert_eq!(actual.len(), expected.len());
    for (index, (actual, expected)) in actual.iter().zip(expected).enumerate() {
        let error = (actual - expected).abs();
        assert!(
            error < 1.0e-12,
            "value {index}: actual={actual}, expected={expected}, error={error}"
        );
    }
}

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let mut backend = CpuBackend::new();

    let a = TypedTensor::<f64>::from_vec_col_major(vec![2, 2], vec![3.0, 0.0, 0.0, 1.0])?;
    let identity = TypedTensor::<f64>::from_vec_col_major(vec![2, 2], vec![1.0, 0.0, 0.0, 1.0])?;

    let product = a.matmul(&identity, &mut backend)?;
    assert_eq!(product.shape(), &[2, 2]);
    assert_close(product.host_data()?, &[3.0, 0.0, 0.0, 1.0]);

    let svd = backend.svd_read(TensorView::F64(product.as_view()))?;
    assert_eq!(svd.len(), 3);
    assert_eq!(svd[0].shape(), &[2, 2]);
    assert_eq!(svd[1].shape(), &[2]);
    assert_eq!(svd[2].shape(), &[2, 2]);
    assert_close(svd[1].as_slice::<f64>().unwrap(), &[3.0, 1.0]);

    Ok(())
}

Dependency Footprint

tenferro-rs dependency footprint

The diagram is a transitive-reduced view of workspace crates generated from the same dependency metadata read by scripts/gen_dep_graph.py.

Mental Model

tenferro has three independent choices. GPU providers, eager execution, and traced graphs are not competing APIs; they answer different questions.

Choice Question Options
Tensor API What kind of value do I pass around? TypedTensor<T>, Tensor, EagerTensor, TracedTensor
Execution timing When does computation run? Direct backend call, immediate eager execution, traced compile/run
Backend/device Where does computation run? CPU, CUDA, or experimental WebGPU backend, with explicit transfer

Most code without autodiff starts with TypedTensor<T> when the scalar type is known at compile time, or Tensor when dtype must be selected at runtime. EagerTensor adds immediate execution through an EagerRuntime, optional stateful backward() on scalar losses, and functional eager grad, vjp, and jvp transforms. TracedTensor adds graph compilation, grad, vjp, and jvp on traced graphs, symbolic inputs, and reuse.

Get In Touch

Questions, design discussions, and contributor coordination for tenferro happen in the tenferro Matrix room:

Matrix is an open, federated chat protocol. You can join from a Matrix client such as Element, or through the browser flow opened by the link above.

Use GitHub issues for bug reports, feature requests, and decisions that need tracking; use Matrix for lightweight discussion before filing or implementing changes.