| Crates.io | scirs2-autograd |
| lib.rs | scirs2-autograd |
| version | 0.1.2 |
| created_at | 2025-04-12 11:23:53.309365+00 |
| updated_at | 2026-01-16 08:27:20.884281+00 |
| description | Automatic differentiation module for SciRS2 (scirs2-autograd) |
| homepage | |
| repository | https://github.com/cool-japan/scirs |
| max_upload_size | |
| id | 1630831 |
| size | 2,529,546 |
Production-Ready Automatic Differentiation for Rust (v0.1.0)
A high-performance automatic differentiation library for SciRS2, providing functionality comparable to PyTorch/TensorFlow's autograd systems with native Rust performance and safety guarantees.
ā ļø SciRS2 POLICY Migration: This module is currently being updated to follow the SciRS2 POLICY - migration from direct rand:: and ndarray:: usage to scirs2-core abstractions is in progress.
Add to your Cargo.toml:
[dependencies]
scirs2-autograd = "0.1.2"
Enable performance optimizations and additional backends:
[dependencies]
scirs2-autograd = { version = "0.1.2", features = ["blas", "simd"] }
Available Features:
blas - BLAS acceleration for linear algebra operationsopenblas - OpenBLAS backendintel-mkl - Intel MKL backend for maximum performancesimd - SIMD acceleration for element-wise operationsuse scirs2_autograd::{run, tensor_ops as T};
// Compute gradients of z = 2x² + 3y + 1
run(|ctx| {
let x = ctx.placeholder("x", &[]);
let y = ctx.placeholder("y", &[]);
let z = 2.0 * x * x + 3.0 * y + 1.0;
// First-order gradients
let dz_dy = &T::grad(&[z], &[y])[0];
println!("dz/dy = {:?}", dz_dy.eval(ctx)); // => 3.0
let dz_dx = &T::grad(&[z], &[x])[0];
let x_val = scirs2_autograd::ndarray::arr0(2.0);
let result = ctx.evaluator()
.push(dz_dx)
.feed(x, x_val.view())
.run()[0];
println!("dz/dx at x=2 = {:?}", result); // => 8.0
// Higher-order derivatives
let d2z_dx2 = &T::grad(&[dz_dx], &[x])[0];
println!("d²z/dx² = {:?}", d2z_dx2.eval(ctx)); // => 4.0
});
use scirs2_autograd::{tensor_ops::*, ndarray_ext, VariableEnvironment};
use scirs2_autograd::optimizers::adam::Adam;
// Build a 2-layer MLP for classification
let mut env = VariableEnvironment::new();
let mut rng = ndarray_ext::ArrayRng::<f32>::default();
// Initialize network parameters
// Note: Use ndarray_ext::zeros for NdArray, not tensor_ops::zeros which returns Tensor
env.name("w1").set(rng.glorot_uniform(&[784, 128]));
env.name("b1").set(ndarray_ext::zeros(&[1, 128]));
env.name("w2").set(rng.glorot_uniform(&[128, 10]));
env.name("b2").set(ndarray_ext::zeros(&[1, 10]));
// Setup Adam optimizer
let adam = Adam::default(
"adam_optimizer",
env.default_namespace().current_var_ids(),
&mut env
);
// Training loop
for epoch in 0..100 {
env.run(|ctx| {
// Input placeholders
let x = ctx.placeholder("x", &[-1, 784]); // batch_size Ć 784
let y_true = ctx.placeholder("y", &[-1]); // batch_size
// Load model parameters
let w1 = ctx.variable("w1");
let b1 = ctx.variable("b1");
let w2 = ctx.variable("w2");
let b2 = ctx.variable("b2");
// Forward pass
let hidden = relu(matmul(x, w1) + b1);
let logits = matmul(hidden, w2) + b2;
// Compute loss
let loss = reduce_mean(
sparse_softmax_cross_entropy(logits, &y_true),
&[0],
false
);
// Backpropagation
let params = [w1, b1, w2, b2];
let gradients = &grad(&[loss], ¶ms);
// Parameter updates would be performed here with actual training data
// adam.update(¶ms, gradients, ctx, feeder);
});
}
ndarray_ext vs tensor_ops FunctionsThere are two sets of array creation functions with different return types:
| Module | Function | Returns | Use For |
|---|---|---|---|
ndarray_ext::zeros |
zeros(&[shape]) |
NdArray<T> |
Variable initialization, data storage |
tensor_ops::zeros |
zeros(&shape, ctx) |
Tensor<F> |
Computation graph operations |
Common Mistake:
// ā WRONG: tensor_ops::zeros returns Tensor, but .set() expects NdArray
use scirs2_autograd::tensor_ops::*;
env.name("b1").set(zeros(&[1, 128], ctx)); // Type error!
// ā
CORRECT: Use ndarray_ext::zeros for variable initialization
use scirs2_autograd::ndarray_ext;
env.name("b1").set(ndarray_ext::zeros(&[1, 128]));
Rule of Thumb:
ndarray_ext::* for data (variable initialization, feeding values)tensor_ops::* for computations (inside env.run(|ctx| { ... }))Gradient checkpointing is a memory optimization technique that trades additional computation time for reduced memory usage during backpropagation. This is especially useful for training large models under memory constraints.
During standard backpropagation, all intermediate activations must be stored to compute gradients, which can lead to high memory usage in deep networks. Gradient checkpointing selectively discards intermediate activations during the forward pass and recomputes them during the backward pass as needed.
use scirs2_autograd::{run, tensor_ops as T};
run(|ctx| {
// 1. Basic checkpointing of individual tensors
let input = T::ones(&[128, 128], ctx);
let w = T::ones(&[128, 128], ctx);
let hidden = T::matmul(&input, &w);
let hidden_checkpoint = T::checkpoint(&hidden); // This tensor will be recomputed during backprop
// 2. Adaptive checkpointing based on memory threshold (in bytes)
let large_tensor = T::matmul(&input, &w);
let adaptive_checkpoint = T::adaptive_checkpoint(&large_tensor, 1_000_000); // 1MB threshold
// 3. Checkpoint groups for multi-output operations
let checkpoint_group = T::CheckpointGroup::new(ctx);
let (output1, output2) = checkpoint_group.checkpoint_fn_flex2(&[&input, &w], |inputs| {
let a = T::matmul(&inputs[0], &inputs[1]);
let b = T::transpose(&a, &[1, 0]);
(a, b) // Both tensors will be checkpointed together
});
});
You can measure the memory savings and performance impact of your checkpointing strategy:
// Start tracking memory usage
T::CheckpointProfiler::start_tracking();
// Your model with checkpointing
// ... (model code with checkpoint operations)
// Evaluate performance
println!("Memory saved: {} KB", T::CheckpointProfiler::memory_saved() / 1024);
println!("Checkpoint operations: {}", T::CheckpointProfiler::checkpoint_count());
// Reset for next test
T::CheckpointProfiler::reset_statistics();
Test Coverage: 404 passing tests, 0 failures
Memory Efficiency: Up to 80% reduction with gradient checkpointing
Numerical Stability: Robust implementations for large-scale computations
Performance: SIMD and multi-threading optimizations throughout
SciRS2 Autograd v0.1.0 is Stable Release and is production-ready:
This project is dual-licensed under:
You can choose to use either license. See the LICENSE file for details.