Docs

Other GPUs

All numbers and reference checks in these docs come from one RTX 5060 Ti 16 GB (sm_120). This page explains what runs on other hardware, how to check your setup, and how to measure your GPU and send us the numbers.

What runs where

portable is plain PyTorch and runs wherever PyTorch runs (CPU, any CUDA GPU, MPS). kernels adds our CUDA kernels. It needs all of the following:

  • Linux on x86-64 with glibc 2.34 or newer. aarch64 hosts (Jetson, Grace, DGX Spark) run portable only.
  • An NVIDIA GPU with compute capability 8.0 or newer.
  • An NVIDIA driver for CUDA 12.8 or newer (driver 570 or newer). The kernels are built with CUDA 12.8, those of GREAT-IGEV, IGEV++, MoCha-Stereo, S2M2 and fvm_conv (all classification families, DINOv3-ConvNeXt, SegFormer) with CUDA 13.0 (driver 580 or newer). These libraries (fvm_conv, igevpp, mocha, s2m2_cutlass) also ship their CUDA 12.8 build, which drivers 570-579 load automatically (fvm_conv's is slower: ResNet-50 core 0.76 instead of 0.64 ms).
  • cuDNN 9 (the copy torch ships): most stereo families build fp16-accumulate cuDNN plans through its backend API.
  • One CUDA device per process for kernels.

Each kernel library ships native code (SASS) for sm_80, 86, 89, 90, 100 and 120, plus PTX for compute_80. A GPU uses the exact SASS if there is one. Otherwise it uses SASS with the same major version and the highest lower minor, otherwise the PTX, which the driver compiles on the first load.

compute capabilityexample GPUskernels usestested
CPUanynot available, portable onlyyes
MPSApple siliconMetal kernels for the families in the table below, else portableM1 Pro (usage, speed); recent Metal changes not yet rechecked
< 8.0T4, V100, RTX 20xx, GTX 10xxnot available, portable onlyno
8.0A100, A30sm_80no
8.6RTX 30xx, A10, A40, RTX A6000sm_86no
8.7Jetson Orinnot available (aarch64)no
8.9RTX 40xx, L4, L40S, RTX 6000 Adasm_89no
9.0H100, H200sm_90no
10.0B200, GB200 (x86-64 hosts only)sm_100no
10.3B300sm_100no
12.0RTX 50xx, RTX PRO 6000 Blackwellsm_120yes (RTX 5060 Ti)
12.1 and newer minorsfuture 12.x GPUssm_120no
newer majorsfuture GPUscompute_80 PTX, JIT on first loadno

"Built but not tested" means the kernels compile for that target, but nobody has checked them against the reference outputs on such a GPU. If kernels gives wrong results, or a different speed-up than Benchmarks, please report it. portable with fp16 is the same PyTorch code on every GPU.

Precision: on CUDA, the default dtype=None uses each model's tested reduced precision (float16, or bfloat16 for DEFOM). GPUs before compute capability 8.0 have no fast bfloat16, so DEFOM computes in float32 there automatically.

mode="auto" (the default) picks kernels when it can load and falls back to portable otherwise. It logs the reason once per load: at WARNING (visible with default logging) when kernels fails on a CUDA device, else at INFO. mode="kernels" never falls back: it raises BackendUnavailableError / KernelUnavailableError with the reason and a remedy.

What each family runs on

Per family (families with the same support share a row; from the model cards; variants of a family share it). CPU: portable, float32 only. kernels runs only on CUDA and on MPS (where listed); all other pairs run portable. fp32 / fp16 / bf16 = float32 / float16 / bfloat16. "MPS portable (validated)" lists the dtypes checked on Apple silicon, the first is the default; - = not validated there (device="mps" still tries, and an op MPS lacks raises).

familiesCUDA portableCUDA kernelsMPS portable (validated)MPS kernels (libraries, dtype)
c_foundationstereo, convnextv2, deit, densenet, depth_anything_v2, detr, dfine, dinov2_linear, dinov2_linear_cls, efficientnet, efficientnetv2, efficientvit, fast_acvnet, fastvit, gwcnet, inception_v3, metric3d, mobilenetv1, mobilenetv2, mobilenetv3, mobilenetv4, mvsanywhere, patchmatchnet, psmnet, rcnn, resnet, rt_monster_plusplus, rtdetrv2, sam, sam2, segformer, shufflenetv2, swin, unidepth_v2, unik3d, vit, waft_stereofp16fp16fp32-
alexnet, cas_gwcnet, coex, depth_anything_3, depth_pro, dinov2, dinov3, dinov3_convnext, dlnr, eomt, eva02, mapanything, marigold, mask2former, midas, mmseg, oneformer, regnet, s2m2, sam3, sapiens, siglip, squeezenet, vgg, vggt_omega, zoedepthfp16fp16fp32/fp16-
cfnet, crestereo, foundationstereo, great_igev, hitnet, igev_plusplus, mocha_stereo, monster, monster_plusplus, raft_stereo, selective_igevfp16fp16fp32/fp16stereo_metal fp16
aanet, bridgedepth, igev_stereo, las2, nmrffp16fp16fp32stereo_metal fp16
mogefp16fp16fp32sparse_metal fp32
defom_stereobf16fp16fp32stereo_metal fp16
vggtfp16fp16fp32vggt_metal fp32

On MPS (Apple silicon), portable works for every validated family and mode="auto" picks the Metal kernels where the card lists mps_kernels (card.kernel_libs_on(device) returns the Metal libraries there, the CUDA ones elsewhere). The Metal kernels compile on the device at first use. They were written and tested on an M1 Pro only; the changes of 2026-11-04 (mps.adapt on all Metal runners, win_rpe_attn sentinel, kernel input guards, rectify in float64 on CPU) still need a check on a Mac.

Kernel libraries per family

Each family's kernels backend needs these libraries; fastforks env shows whether a binary exists for your GPU.

libraryfamilies
cfsc_foundationstereo
crestereocrestereo
cudnn_haccaanet, alexnet, c_foundationstereo, cas_gwcnet, cfnet, coex, convnextv2, crestereo, defom_stereo, deit, densenet, detr, dfine, dinov2_linear_cls, dlnr, efficientnet, efficientnetv2, efficientvit, eva02, fast_acvnet, fastvit, foundationstereo, great_igev, gwcnet, igev_plusplus, igev_stereo, inception_v3, las2, marigold, midas, mmseg, mobilenetv1, mobilenetv2, mobilenetv3, mobilenetv4, mocha_stereo, monster, monster_plusplus, mvsanywhere, psmnet, raft_stereo, rcnn, regnet, resnet, rt_monster_plusplus, rtdetrv2, s2m2, sam3, sapiens, segformer, selective_igev, shufflenetv2, siglip, squeezenet, swin, unidepth_v2, vgg, vggt, vit, waft_stereo, zoedepth
cutlass_convaanet, c_foundationstereo, cas_gwcnet, cfnet, coex, crestereo, defom_stereo, dlnr, fast_acvnet, great_igev, gwcnet, igev_plusplus, igev_stereo, las2, mmseg, mocha_stereo, monster, monster_plusplus, mvsanywhere, psmnet, raft_stereo, rt_monster_plusplus, selective_igev, waft_stereo
deform_convaanet
dpt_fuseddepth_anything_3, depth_anything_v2, depth_pro, moge, sam, sam2, unidepth_v2, unik3d
fastbbbridgedepth, c_foundationstereo, crestereo, defom_stereo, depth_anything_3, depth_anything_v2, depth_pro, dinov2, dinov2_linear, dinov3, dlnr, eomt, foundationstereo, mapanything, metric3d, moge, monster, monster_plusplus, mvsanywhere, nmrf, rt_monster_plusplus, sam3, sapiens, unidepth_v2, unik3d, vggt, vggt_omega, waft_stereo
ffs_cutlassc_foundationstereo
fsc_foundationstereo, foundationstereo
fs_cutlassc_foundationstereo, foundationstereo
fvm_convalexnet, convnextv2, deit, densenet, dinov2_linear_cls, dinov3_convnext, efficientnet, efficientnetv2, efficientvit, eva02, fastvit, inception_v3, mobilenetv1, mobilenetv2, mobilenetv3, mobilenetv4, regnet, resnet, segformer, shufflenetv2, siglip, squeezenet, swin, vgg, vit
fvm_extraalexnet, convnextv2, deit, densenet, dinov2_linear_cls, efficientnet, efficientnetv2, efficientvit, eva02, fastvit, inception_v3, mobilenetv1, mobilenetv2, mobilenetv3, mobilenetv4, regnet, resnet, segformer, shufflenetv2, siglip, squeezenet, swin, vgg, vit
fvm_mbalexnet, convnextv2, deit, densenet, dinov2_linear_cls, efficientnet, efficientnetv2, efficientvit, eva02, fastvit, inception_v3, mobilenetv1, mobilenetv2, mobilenetv3, mobilenetv4, regnet, resnet, segformer, shufflenetv2, siglip, squeezenet, swin, vgg, vit
fvm_r3alexnet, convnextv2, deit, densenet, dinov2_linear_cls, efficientnet, efficientnetv2, efficientvit, eva02, fastvit, inception_v3, mobilenetv1, mobilenetv2, mobilenetv3, mobilenetv4, regnet, resnet, segformer, shufflenetv2, siglip, squeezenet, swin, vgg, vit
fvm_segdinov3_convnext, mask2former, oneformer
hitnethitnet
hitnet_convhitnet
igevaanet, c_foundationstereo, cas_gwcnet, cfnet, coex, crestereo, defom_stereo, dlnr, fast_acvnet, great_igev, gwcnet, igev_plusplus, igev_stereo, las2, mmseg, mocha_stereo, monster, monster_plusplus, mvsanywhere, psmnet, rt_monster_plusplus, selective_igev, waft_stereo
igevppgreat_igev, igev_plusplus, monster_plusplus
mochamocha_stereo
mvsanywheremvsanywhere
patchmatchnetpatchmatchnet
raftdlnr, raft_stereo
s2m2s2m2
s2m2_cutlasss2m2
seg_convmmseg
seg_updinov2_linear, eomt, mask2former, mmseg, oneformer, sapiens, segformer
sparse_convmoge
stereo_opscoex, las2
vggt_omegavggt_omega

Check your setup

fastforks env

This prints the fastforks, Python, torch, CUDA, cuDNN and driver versions, and the GPU with its compute capability. For each kernel library it shows which binary your GPU would use and whether it is already downloaded. Example on the tested machine (RTX 5060 Ti, 2026-10-27):

fastforks              0.1.0
python                 3.12.15 (linux x86_64)
torch                  2.14.1+cu130 (CUDA 13.0, cuDNN 92400)
driver                 supports CUDA 13.2
gpu                    NVIDIA GeForce RTX 5060 Ti, sm_120
kernels cfs            sm_120, local
kernels crestereo      sm_120, local
kernels cudnn_hacc     no binaries: cuDNN plans via the cuDNN backend API (cuDNN 9.24.0)
kernels cutlass_conv   sm_120, local
kernels fastbb         sm_120, local
kernels fs             sm_120, local
kernels fs_cutlass     sm_120, local
kernels hitnet         sm_120, local
kernels hitnet_conv    sm_120, local
kernels igev           sm_120, local
kernels raft           sm_120, local
kernels s2m2           sm_120, local
kernels s2m2_cutlass   sm_120, local

Possible states of a kernel library:

statemeaning
sm_XY, localready
sm_XY, not downloaded yet (fastforks download --kernels)downloaded on the first kernels load, or now with fastforks download MODEL --kernels
compute_80 (PTX, JIT-compiled on first load), localno native code for this GPU: the first load takes longer and speed is untested
no binary for sm_XY (built: ...)GPU too old (< 8.0): portable only
..., but needs a driver for CUDA >= 12.8 (have ...)update the NVIDIA driver
built for ...; no CUDA GPUno GPU visible to torch
cuDNN plans ... (unusable: ...)torch's cuDNN 9 (libcudnn.so.9) cannot be loaded: reinstall torch

Which backend a loaded model uses:

import logging

from fastforks import stereo

logging.basicConfig(level=logging.INFO)  # shows every backend choice, e.g. "kernels unavailable (...); using portable"
model = stereo.load("las2-s")
print(model.backend.mode)  # "kernels" or "portable"
stereo.load("las2-s", mode="kernels")  # raises with the reason instead of falling back

Offline machines: download weights and kernels on a machine with internet, copy the cache, and point FASTFORKS_CACHE at the copy.

fastforks download las2-s depth-anything-v2-s --kernels --all-archs   # --all-archs: binaries for every target
# copy the cache folder (see FASTFORKS_CACHE) to the offline machine, then there:
export FASTFORKS_CACHE=/path/to/copy FASTFORKS_OFFLINE=1

Common errors

message containsfix
no binary for sm_75GPU older than compute capability 8.0: use mode="portable" (or auto)
update the NVIDIA driver to >= 570 (or 580)the kernels need a driver for their CUDA version (12.8, or 13.0)
backend API is not usable: ...torch's cuDNN 9 (libcudnn.so.9) cannot be loaded: reinstall torch
cannot download ... fastforks download --kernelsno network: download on another machine, set FASTFORKS_CACHE to a copy of the cache (see Offline machines above)
built for Linux x86-64 / needs a CUDA device / ROCm/HIPportable only on this host
kernels already runs on cuda:0 in this processthe kernels and their buffers are per process: use one process per GPU

Measure your GPU

fastforks bench times one model on a synthetic image (a pair for stereo). It runs 4 warm-up calls, then prints the median of --runs calls and the peak memory of the torch allocator:

fastforks bench las2-s --mode kernels --size 375x1242 --runs 20
fastforks bench las2-s --mode portable --size 375x1242 --runs 20

Output of the two commands on the tested machine (2026-11-05):

las2-s@1 375x1242 kernels float16: 4.0 ms (median of 20), peak 115 MiB allocated / 326 MiB reserved
las2-s@1 375x1242 portable float16: 20.5 ms (median of 20), peak 302 MiB allocated / 330 MiB reserved

To measure the models of the Benchmarks tables in both modes and save everything to one file:

gpu=$(nvidia-smi --query-gpu=name --format=csv,noheader | head -1 | tr ' ' '_')
out=fastforks_bench_$gpu.txt
fastforks env > "$out"
for m in las2-s hitnet-eth3d coex-sceneflow s2m2-s igev-stereo-sceneflow crestereo-eth3d depth-anything-v2-s; do
  for mode in kernels portable; do
    fastforks bench "$m" --mode "$mode" --size 375x1242 --runs 20 2>&1 | tee -a "$out"
  done
done

Close other GPU programs first. Laptop GPUs and GPUs without a fixed clock vary by 5-10 % between runs, so run the loop twice and report both runs.

Check that kernels and portable agree on your GPU:

import numpy as np

from fastforks import stereo

rng = np.random.default_rng(0)
left = rng.integers(0, 256, (375, 1242, 3), dtype=np.uint8)
right = np.roll(left, -8, axis=1)
a = stereo.load("las2-s", mode="kernels")(left, right).disparity
b = stereo.load("las2-s", mode="portable")(left, right).disparity
print("max |kernels - portable| px:", (a - b).abs().max().item(), "mean:", (a - b).abs().mean().item())

On the tested machine this prints max |kernels - portable| px: 4.794837951660156 mean: 0.1790103018283844 (2026-10-27). Random images have no real structure, so single pixels can differ by several pixels of disparity: compare the mean. The GPU reference tests compare both modes with one stored reference output on a synthetic pair (tests/synth.py), by the mean and the 99th percentile of the difference.

Contributing numbers

Open an issue at github.com/kleinicke/fastforks titled "Numbers: " and attach:

  1. the fastforks env output,
  2. the bench file from the loop above (both runs),
  3. the output of the agreement snippet,
  4. anything unusual: errors, a slow first load (PTX JIT), clocks locked or not, laptop or desktop.

Numbers from untested architectures (everything except sm_120) are the most useful. If a kernels load fails, the full error message and fastforks env are enough.