Compute Backends

A backend is selected with --backend (CLI and server) and decides which hardware runs the math. Every backend falls back to CPU for any unimplemented op, so output stays correct everywhere — backends differ only in speed.

Which backend should I use?

Your hardwareRecommendedFlagNotes
Apple Silicon (Mac)GGML Metalggml_metalDefault on macOS. mlx is an alternative Apple-Silicon GPU path.
Windows / Linux + NVIDIAGGML CUDAggml_cudaMost-tested NVIDIA path. cuda is the direct PTX/cuBLAS backend for experimentation — and the one that supports multi-GPU tensor parallelism.
Windows / Linux + AMD / Intel / NVIDIAGGML Vulkanggml_vulkanVendor-neutral GPU path via ggml-vulkan (cooperative-matrix accelerated where the driver supports it). Built automatically when the machine has a Vulkan runtime; opt out with --no-vulkan.
No GPU / portability / debuggingPure C# CPUcpuNo native dependencies. For faster CPU inference use ggml_cpu (native kernels).

All backends in detail

BackendFlagBest fit
Direct CUDA / cuBLAScudaNVIDIA inference & experimentation
MLX MetalmlxApple Silicon (alternative to GGML Metal)
GGML Metalggml_metalApple Silicon (default on macOS)
GGML CUDAggml_cudaNVIDIA inference through ggml
GGML Vulkanggml_vulkanVendor-neutral GPU inference through ggml (AMD / Intel / NVIDIA)
GGML CPUggml_cpuNative CPU kernels
Pure C# CPUcpuPortability & debugging

GGML Metal, GGML CUDA & GGML Vulkan

The GPU paths built on a native C++ bridge that links ggml.

All three run native quantized matmul (Q4_K_M, Q8_0, …) without dequantizing to FP32, plus a native paged-attention kernel that drives ggml_flash_attn_ext.

Multi-GPU. GGML CUDA and GGML Vulkan also support tensor parallelism: --tp N gives each rank its own ggml backend, weight shards, and KV cache on its own GPU, driven concurrently by a rank worker pool, with cross-GPU AllReduce through ggml's collective (NCCL when the build finds it) or a host reduction for small payloads. Fused per-rank block graphs make --tp 2 decode faster than a single GPU on Gemma 4, and let models larger than one card's VRAM run entirely on GPUs.

Verified E4B fast lane: repository benchmarks exercise the Gemma 4 E4B Q8_0 family on these native GGML GPU backends. E4B's PLE and shared-KV layout stays on the fused whole-model prefill/verify and single-graph decode paths, with automatic fused N=1 server routing. Start with the Gemma 4 E4B guide.

MLX Metal

--backend mlx is a GPU-accelerated Apple-Silicon path built on mlx-c. It implements quantized ops (Q4_K_M, Q8_0, Q5_K, Q6_K, IQ2_XXS, IQ4_XS, IQ4_NL, MXFP4, …) without dequantizing to FP32, fused decode/prefill Metal kernels, compiled-graph kernels, async worker dispatch, batched MoE decode, and MoE expert offload. It pins the GGUF mmap in physical RAM via mlock(2) and derives allocator caps from the host's unified-memory capacity. Requires libmlxc (built locally or located via TENSORSHARP_MLX_LIBRARY / TENSORSHARP_MLX_LIBRARY_DIR).

Direct CUDA

--backend cuda is a pure-C# path using the CUDA Driver API, cuBLAS GEMM, and PTX kernels for common float32 ops (fill, unary/binary/ternary, activations, RMSNorm, softmax, RoPE/RoPEEx, SDPA, GQA prefill/decode, causal mask, gather/concat) plus native quantized matmul/get-rows for supported quant types. Unsupported ops route through CPU fallbacks while preserving tensor semantics. It is also the pure-C# backend where MTP speculative decoding is profitable.

It supports tensor parallelism: --tp N shards one model across N CUDA GPUs, and --tp-node-id / --tp-peers extend the group across machines. The GGML CUDA and GGML Vulkan backends shard too (see above); MLX and the CPU backends are single-device — on a multi-GPU host they pick one device (--gpu-device for Vulkan without --tp) rather than splitting the model. → Multi-GPU & Multi-Node

CPU backends

DeepSeek V4: dedicated whole-model executors

deepseek4 is the one architecture that does not use the generic per-op forward on any backend. Its 284B compressed-sparse-attention MoE stack runs through one of three dedicated whole-model executors instead:

All three layer-split the weights across every visible GPU (the CPU one streams them from the mapped shards), so a model far larger than one card still runs; --tp N or TS_DSV4_NGPU caps how many GPUs are used. Speculative decoding (DSpark) is available on the two GPU engines. → DeepSeek V4 downloads and commands

🔎

The server reports which backends are actually available on the host in GET /api/models (supportedBackends). If a CUDA or MLX backend is missing, the host did not detect a usable driver/runtime at startup. If ggml_vulkan is missing, the native bridge was not built with Vulkan enabled or no Vulkan 1.3 device/driver was found.

Building the native libraries

First install and verify the .NET 10 SDK for your platform. The native GGML library is built automatically on the first dotnet build. To build it manually or with CUDA:

cd TensorSharp.GGML.Native

# macOS (Metal)
bash build-macos.sh

# Linux — CPU only, force CUDA on, force Vulkan off
bash build-linux.sh
bash build-linux.sh --cuda
bash build-linux.sh --no-vulkan
# Windows — CPU only, force CUDA on, force Vulkan off
.\build-windows.ps1 --no-cuda
.\build-windows.ps1 --cuda
.\build-windows.ps1 --no-vulkan

The GGML Vulkan backend is enabled automatically when the machine has a Vulkan runtime (a loader such as vulkan-1.dll on Windows or libvulkan.so.1 on Linux, shipped by every recent GPU driver); opt out with --no-vulkan (or TENSORSHARP_GGML_NATIVE_ENABLE_VULKAN=OFF), and an explicit choice sticks across rebuilds via the CMake cache. On Windows, a LunarG Vulkan SDK is used when installed; without one the build auto-provisions a portable toolchain (Vulkan-Headers, a vulkan-1 import library generated from the system loader, glslc, SPIRV-Headers) into ExternalProjects/vulkan-toolchain/ via eng/fetch-vulkan-toolchain.ps1. On Linux, distro dev packages are used when present (apt install libvulkan-dev glslc spirv-headers); otherwise the build auto-provisions the missing pieces (Vulkan-Headers, glslc from the shaderc CI prebuilts, SPIRV-Headers) via eng/fetch-vulkan-toolchain.sh. A GPU driver with Vulkan 1.3 support is required at run time.

On Windows/Linux the script auto-detects the visible NVIDIA GPU compute capability and passes a narrow CMAKE_CUDA_ARCHITECTURES (e.g. 86-real on an RTX 3080), which cuts CUDA build time substantially. Override it explicitly:

TENSORSHARP_GGML_NATIVE_CUDA_ARCHITECTURES='86-real;89-real' bash build-linux.sh --cuda
bash build-linux.sh --cuda --cuda-arch='86-real;89-real'

You can also request CUDA from dotnet build directly:

TENSORSHARP_GGML_NATIVE_ENABLE_CUDA=ON dotnet build TensorSharp.Cli/TensorSharp.Cli.csproj -c Release

MLX native library (macOS only)

The MLX backend depends on libmlxc. A helper script fetches and builds it:

bash TensorSharp.Backends.MLX/build-native-macos.sh

It writes the libraries into TensorSharp.Backends.MLX/Native/dist/. At run time the backend probes the application directory first; point it elsewhere with TENSORSHARP_MLX_LIBRARY or TENSORSHARP_MLX_LIBRARY_DIR.

Platform binary release status

⚠️

The current latest release, v3.0.5.0, has no uploaded application archives. Build from source unless an archive is visibly listed on the Releases page.

The release workflow is intended to create the following self-contained archives after every required build job succeeds:

ArchiveNative backend(s) bundledFormat
win-x64-cpuGGML CPU.zip
win-x64-cudaGGML CUDA + pure-C# CUDA (PTX) + CUDA 12.x runtime.zip
linux-x64-cpuGGML CPU.tar.gz
linux-x64-cudaGGML CUDA + pure-C# CUDA (PTX) + CUDA 12.x runtime.tar.gz
osx-arm64GGML Metal + MLX.tar.gz

These are intended artifact names, not a claim that the files are currently downloadable. When present, -cuda archives still require an NVIDIA GPU and compatible driver; the macOS archive requires Apple Silicon.