std1.0.0-beta-7 SafeC docs

Module ml::tensor_auto

#include <std/ml/tensor_auto.h> source

size-based automatic backend selection for Tensor ops on the CPU (mixing SIMD/vDSP/BLAS, chosen FOR the caller instead of BY the caller; GPU placement is device.h's job).

device.h already lets a caller pick a device explicitly. What it doesn't do is pick the RIGHT one automatically — every backend has a size range where it's the wrong choice (BLAS's own per-call setup overhead costs more than a tiny naive loop saves; vDSP has the same shape of overhead; GPU's command-buffer submission cost dominates below a problem size that, in this codebase's own benchmarks, no shape tried so far has reached). The functions here measure that instead of guessing, and pick per call — see tensor_auto.sc for the actual thresholds and how they were obtained.

Deliberately CPU-only for now: matmul benchmarked from 2x2x2 up to 128x128x128 never found a size where the naive loop beat BLAS (BLAS won or tied at every point tested — see tensor_auto.sc), and this project's own from-scratch GPU benchmarks (see benchmarks.md's "GPU is slower than CPU here" and "GPU backward was the real bottleneck" findings) never found a shape where MPS beat BLAS either, up to and including a 128x512x1024x256 training step. Auto-selecting GPU would mean picking it on the strength of zero measured wins — not done here. A caller who wants GPU regardless (e.g. because their real workload is larger than anything benchmarked so far, or to free up the CPU for other work) should keep using tensor_matmul_on(..., DEVICE_MPS) explicitly; that path doesn't disappear, this file just doesn't add GPU to what "auto" means until there's a measured case for it.

Apple's Neural Engine (ANE/"NPU") isn't offered as an option at all, automatic or explicit: unlike Metal, there is no public low-level API to submit an arbitrary compute kernel to the ANE the way gpu_mps.sc submits one to the GPU. The only supported path is CoreML — hand it a whole compiled model graph (an .mlmodel/.mlpackage) via MLModel and let CoreML's own scheduler decide ANE vs GPU vs CPU internally, not "call a function, get a kernel to run." That's a fundamentally different integration (author/compile a model graph, not link a kernel function) and a substantially larger undertaking than everything else in std/ml — not attempted here, and not something this file's Device-enum-style dispatch could grow into incrementally.

Functions

tensor_add_auto
tensor_sub_auto
tensor_mul_auto
tensor_matmul_autoNo size check at all: benchmarked 2x2x2 through 128x128x128 (8 to ~2,097,152 multiply-adds) and BLAS won or tied at every single point — no naive-wins region was ever found, unlike vDSP's real one above. This project's own two training-loop benchmarks (128x256x64 and 128x512x1024x256) independently confirm the same thing at much larger scale. Always dispatching to BLAS here isn't a shortcut that skipped measuring the small-size case — it's what measuring the small-size case actually found.