A GPU buffer copy that silently reports success without moving a byte is worse than a crash — a crash tells you something is wrong.
Today we released ToRSh 0.2.0 — the production-hardening release. Two threads converge here: a Python-bindings push that makes ToRSh’s rstorch package genuinely PyTorch-compatible, and a 13-agent audit that went crate by crate looking for exactly the class of bug the opening line describes — code that looks like it succeeded and didn’t.
ToRSh — “Tensor Operations in Rust with Sharding” — is a PyTorch-compatible deep-learning framework built entirely in pure Rust. No C. No C++. No Fortran. No Python runtime required to run inference. Where PyTorch depends on libtorch/ATen, a full CUDA toolchain, and a Python interpreter, ToRSh compiles to a single static binary you can ship to bare metal, a container, or WASM with nothing else installed. As of 0.2.0, the CUDA story is also unified: the legacy CUDA C-FFI backend — and its cust, cuda-sys, and cudnn-sys dependencies — is gone. Every GPU path now runs through the pure-Rust OxiCUDA stack.
Why ToRSh 0.2.0 is a game changer
Machine-learning frameworks tend to fail in one particular way: silently. A gradient that’s quietly zero instead of computed. A buffer copy that reports success without moving any data. A distributed barrier that’s secretly a no-op because a handle was dropped too early. A state_dict() that hands back an empty placeholder instead of your optimizer’s real momentum buffers. None of these crash. Your training run finishes, the loss curve looks plausible, and the bug ships.
ToRSh 0.2.0 goes after exactly that class of bug:
- Autograd backward coverage, completed.
mul,div,matmul,cat,stack,narrow, andlog_softmaxnow compute real gradients — paths that previously returned zero or were flatly unimplemented. - The WebGPU buffer-copy bug.
copy_buffer/copy_to_device/copy_from_devicesilently returned success without moving any data — and the old buffer lookup cast an opaque handle ID to a rawwgpu::Bufferpointer, which was undefined behavior. Both are fixed; copies now actually copy. - The MPI barrier that never was. The
Universehandle backing the MPI backend was dropped immediately after construction, which finalizes MPI — so every later MPI call,barrier()included, quietly failed. The handle is now held for the backend’s lifetime. - Real Python optimizer checkpoints.
state_dict()/load_state_dict()on theSGD,Adam,AdamW,Adagrad, andRMSpropPython bindings now carry the actual per-parameter buffers — momentum,exp_avg,exp_avg_sq, step count — instead of an empty placeholder. Training can actually resume from a saved checkpoint. - RNG seeding, for real. A fixed seed (e.g.
42) previously did not make sampling deterministic. Seeded generators now reproduce their sequence. - One CUDA stack, not two. GPU compute is now provided exclusively by pure-Rust OxiCUDA; the duplicated legacy CUDA C-FFI backend was deleted outright rather than left to bit-rot alongside it.
Technical Deep Dive: hardening the stack
The autograd layer. torsh-autograd fills in the backward passes that were silently short-circuiting: mul/div/matmul/cat/stack/narrow/log_softmax all get real gradient implementations. HyperparameterOptimizer now computes real first-order gradients via central finite differences instead of unconditionally returning zero, so gradient-based hyperparameter search can actually move a hyperparameter toward its optimum.
The GPU layer. With the legacy CUDA C-FFI backend removed, torsh-tensor’s runtime-loaded GpuDispatch is the only path to the GPU, backed by the OxiCUDA stack (oxicuda-backend/driver/launch/ptx, bumped to 0.5.4). torsh-backend’s cuda feature is now an honest pure-Rust fallback: unsupported ops return a clear error or route to CPU, rather than silently degrading.
The Python bindings layer. torsh-python migrates to pyo3 0.29 (numpy 0.29, scirs2-numpy 0.6.0), which exposed — and let us fix — a signature-annotation gap where 31 tensor-creation and reduction methods required every optional argument to be passed explicitly. On top of that: real Tensor operator overloads (__add__, __sub__, __mul__, __truediv__, __matmul__, __neg__), a rstorch.optim.lr_scheduler submodule with 6 PyTorch-compatible schedulers, and a full NumPy/pandas/SciPy interop bridge in torsh-ffi — tensor↔ndarray conversion, DataFrame↔tensor plus merge/pivot/time-series helpers, and SciPy solve/eig/svd/minimize/fft bindings that were previously all placeholder stubs returning “not implemented.”
The security layer. Archive extraction in torsh-hub / torsh-package is now hardened against path-traversal (tar-slip / zip-slip) — entry paths are validated and rejected if they’d escape the destination directory. Downloaded and unpacked artifacts get integrity checks against tampering or truncation. Package signing runs through pure-Rust ed25519-dalek — no C/asm crypto anywhere in the path.
Getting Started
cargo add torsh
# Enable the GPU backend (runtime CUDA driver load via OxiCUDA — no SDK required at build time)
cargo add torsh --features cuda
use torsh::prelude::*;
fn main() -> Result<()> {
let x = tensor![[1.0, 2.0], [3.0, 4.0]].requires_grad();
let y = x.matmul(&x)?; // matmul now has a real backward gradient
let loss = y.sum()?;
loss.backward()?;
println!("grad: {:?}", x.grad());
Ok(())
}
From Python, the bindings now feel like PyTorch:
import rstorch
from rstorch.optim.lr_scheduler import CosineAnnealingLR
x = rstorch.randn(4, 4, requires_grad=True)
y = x @ x # __matmul__ operator overload
loss = y.sum()
loss.backward()
opt = rstorch.optim.Adam([x], lr=0.01)
scheduler = CosineAnnealingLR(opt, T_max=100)
opt.step()
scheduler.step()
checkpoint = opt.state_dict() # real momentum / exp_avg buffers, not a placeholder
What’s New in 0.2.0
Added
rstorch.optim.lr_scheduler:StepLR,MultiStepLR,ExponentialLR,CosineAnnealingLR,LinearLR,ReduceLROnPlateau- Real Python optimizer
state_dict()/load_state_dict()acrossSGD/Adam/AdamW/Adagrad/RMSprop - Tensor operator overloads on the Python bindings (
__add__,__sub__,__mul__,__truediv__,__matmul__,__neg__) Tensor::norm_lp(p, dims, keepdim): general Lp-norm matchingtorch.normsemantics- Full NumPy / pandas / SciPy interop bridge in
torsh-ffi(previously all placeholder stubs) FloatElementforf16/bf16—epsilon()/infinity()/nan()/is_finite()on half-precision tensors- Real TCP distributed backend (
torsh-distributed), replacing the previous mock - Completed autograd backward coverage:
mul,div,matmul,cat,stack,narrow,log_softmax - Real FIR/IIR filter design,
eig, and SVD intorsh-signal
Changed
- Dependency truth-up:
scirs2→ 0.6.5,oxicuda-*→ 0.5.4,oxifft→ 0.4.2,oxiarc-*→ 0.4.1,oxicode→ 0.2.6,oxionnx→ 0.1.6,wgpu→ 30.0.0,pyo3→ 0.29.0 - CUDA backend consolidated exclusively onto the pure-Rust OxiCUDA stack
TensorParallel::parallel_all_gathernow takes an explicitshard_dimparameter (breaking change)
Fixed
- 31 Python tensor-creation/reduction methods now honor default arguments correctly (pyo3 0.29 signature-annotation gap)
Tensor.norm()(Python) now honorsp/dim/keepdiminstead of always returning the whole-tensor L2 normset_lr()on PythonAdam/AdamW/Adagrad/RMSpropnow actually propagates to the wrapped optimizer- WebGPU buffer copies now perform real GPU-to-GPU data movement (previously a silent no-op with an unsound pointer cast)
- Wavelet Packet Transform / lifting DWT-IDWT (
torsh-signal) run the real transforms instead of returning zero tensors parallel_all_gather(torsh-distributed) concatenates every shard instead of discarding all but one; MPIbarrier()fixed- An alignment-UB bug in tensor lazy-loading (found via Miri) and a mutex-poisoning cascade in the memory pool
torsh-cli info: memory readings no longer inflated 1024x;completionsno longer leaks a log line onto stdout
Security
- Path-traversal (tar-slip / zip-slip) guards on archive extraction in
torsh-hub/torsh-package - Integrity checks on downloaded/unpacked artifacts
- Ed25519 package signing via pure-Rust
ed25519-dalek
Removed
- Legacy CUDA C-FFI backend and its dependencies (
cust,cuda-sys,cudnn-sys) OptiRSdependency (zero use sites), dropping a duplicate SciRS2 0.4.4 stack andndarray0.15 from the tree
Tips
- Resume training from a real checkpoint.
opt.state_dict()on any of the five Python optimizer bindings now round-trips actual momentum/exp_avg/exp_avg_sq/step-count buffers —opt.load_state_dict(checkpoint)picks up exactly where training left off. - Reach for the new LR schedulers instead of hand-rolling one.
from rstorch.optim.lr_scheduler import CosineAnnealingLR, ReduceLROnPlateau, ...— all six are PyTorch-signature-compatible. - Use
Tensor::norm_lpfor anything beyond L2. One function covers L0, L1, L2, max, min, and arbitrary finitep, with per-dimension reduction andkeepdim— matchestorch.normsemantics directly. - If you were on the legacy CUDA C-FFI backend, move to the
cudafeature now. It’s the only GPU path left, and it loads the driver at runtime via OxiCUDA — no CUDA SDK needed at build time, and the binary still runs on CPU-only boxes. - Trust your seeds again. If you were working around non-deterministic runs under a fixed seed, that workaround is no longer necessary — seeded generators reproduce their sequence.
- Cross into NumPy/pandas/SciPy without leaving Rust call sites.
torsh-ffi’s interop bridge now does real tensor↔ndarray conversion and DataFrame↔tensor round-trips, not stub errors.
This is the foundation
ToRSh 0.2.0 is powered by — and in turn powers — the wider COOLJAPAN ecosystem:
- OxiCUDA 0.5.4 (
oxicuda-backend,oxicuda-driver,oxicuda-launch,oxicuda-ptx) — the sole pure-Rust GPU compute stack now that the legacy C-FFI backend is gone - SciRS2 0.6.5 — the scientific-computing foundation: SIMD ops, BLAS, FFT, autograd, sparse, signal, graph, series, vision, text, and more
- OxiBLAS — pure-Rust BLAS/LAPACK, reached through
scirs2-core’soxiblas-blas/oxiblas-lapackfeatures - OxiARC 0.4.1 — pure-Rust compression/archives, now hardened against tar-slip/zip-slip for model-hub extraction
- OxiCode 0.2.6 — binary serialization for model checkpoints
- OxiFFT 0.4.2 — FFT throughout the signal and series crates
- OxiONNX 0.1.6 — ONNX interop
- ed25519-dalek — pure-Rust Ed25519 signing for package integrity
Repository: https://github.com/cool-japan/torsh
Star the repo if a deep-learning framework that would rather return an honest Err than a fabricated success is something you want more of.
The era of ML frameworks that fail silently is over. Pure Rust deep learning is here — fast, safe, and sovereign.
— KitaSan at COOLJAPAN OÜ
August 14, 2026