Skip to content

RTX 5070 Ti bring-up

Run from the repository with Python 3.12, torch 2.7.1+cu128, numpy and pytest. The October 2026 test machine is WSL, RTX 5070 Ti, sm_120, 70 SMs. Its existing Windows host driver works. WSL uses that driver; do not install a Linux display driver inside WSL. CUDA 12.8 is needed to build sm_120 probe extensions.

export PYTHONDONTWRITEBYTECODE=1
export PYTHONPATH="$PWD"
export OMP_NUM_THREADS=4 MKL_NUM_THREADS=4
export CUDA_HOME=<CUDA 12.8 toolkit>                # nvcc >= 12.8 for the sm_120 probe builds
export PATH=<venv>/bin:$CUDA_HOME/bin:$PATH
export MMAEMU_TRUTH_DIR=<truth checkout>             # the unpublished hardware ground truth (G3)
export MMAEMU_GPU_LOCK="flock -w 3600 /tmp/mmaemu-gpu.lock"   # GPU lock command prefix (default: in $TMPDIR)
export MMAEMU_CACHE_DIR="$PWD/build/mmaemu-cache"
python tools/bringup/run_bringup.py

Every command runs under timeout 580, except G1's T3 step: it runs the whole tools/run_gpu_tests.sh, which takes the GPU lock and a 600-second timeout for each test file itself (about 280 s in all on the RTX 5070 Ti, about 560 s on an RTX 4060). Each other GPU command takes the GPU lock separately (the lock prefix above waits up to 3600 s); build and CPU analysis commands run outside the lock. The shipped fatbins in mmaemu/backends/cuda/bin are tested; to test a local build instead, run python tools/build_fatbin.py --release --out build/fatbin and export MMAEMU_FATBIN_DIR=$PWD/build/fatbin. An inherited lock is detected to avoid taking the same lock twice. Prefer running the runner outside the lock so CPU work does not hold the GPU lock.

Each run creates a unique directory under results/bringup/. --out DIR requires a new directory. --stage G8 runs just that gate; --from G8 resumes at G8 in a new directory, preserving earlier evidence. --dry-run executes G0-G3, G8 and G10 on sm_89 or sm_120 and skips native research. --stage G4 --force-fail G4 must fail and name G4 in summary.json. G0 and G2 write the GPU's UUID (info.json, selftest.json); redact it before committing bring-up outputs.

Gate Evidence and acceptance
G0 GPU, driver, libraries, compiler, info and host-clock status. Use CUDA events when the host clock fails.
G1 CPU suite and per-file T3 GPU suite; zero unexpected failures. Ada profile-device tests skip on sm_120.
G2 v1/v4 selftests pass; v9 window result recorded; tc3 has no supported sm_120 binary.
G3 Full hashes of all 21 Evo2 accumulators for v1/v4/v9. v9 is explicitly opted in for this measurement.
G4 c6 native FP8 instructions, including kind::f8f6f4, scored against all hypotheses. No preset is changed.
G5 cuBLAS kit and full bf16 GEMMs with nonunit scales, kernel names and logged split-K. Native/Ada differences are recorded; probe errors stop the run.
G6 Candidate cuBLASLt heuristic table at 0/1/4/32 MiB, kept outside package data.
G7 Signed zero, NaN, underflow/overflow, FP8 saturation and scale_result; production-shape epilogue ties. CPU/GPU twins and tie replay must pass.
G8 Raw bf16 window measurements and CPU analysis; design-A rejection and design-B measurements. Native model scores are observations.
G9 Six Evo2 1B windows in native/emulate/compat/auto modes using a local Evo 2 consumer checkout (--evo2-root or EVO2_ROOT) and the Ada golden outputs (--golden or MMAEMU_EVO2_GOLDEN).
G10 CUDA-event timing for all three projection sizes, v1/v4/v9, with numerical checks before timing.

G4-G9 native observations characterize the new GPU. They do not change the Ada numerical contract. A native mismatch in G5 exits 1 in g1_cublas.py and is retained as a measured difference by the runner. Full-model cross-device comparisons require identical windows, shapes, dtypes and token IDs before computing tolerances; bitwise claims apply to the FP8 GEMMs. Candidate native model loss simulation remains research work and is not a shipped profile.

All probe inputs and sources are vendored with SHA-256 provenance; runtime outputs and caches stay in the new run directory. The c6 README is the audit's, unmodified: its ../family.py is vendored as c6/family.py, while ../pool.py, ../results/ and the MM_sm90mma and MM_cublas64 sets (GH200) are not vendored. Truth, audit recordings and Ada golden files are read-only. G3 requires the pinned local truth package (the runner refuses G3 and G9 without MMAEMU_TRUTH_DIR); G9 additionally requires cached model blocks and the local consumer. The truth, the golden files and the consumer are maintainer-only data, so G3 and G9 run only on the maintainer's host.