rlx-bench 0.2.17

PLAN L5 — uniform benchmark harness for RLX backends + patterns
Documentation
# rlx-bench

Uniform benchmark harness for RLX backends + workload patterns. The
canonical answer for "how fast does my graph run on Device X with
PrecisionPolicy Y?"

## What's here

- **`BenchmarkPattern`** — common workload shapes (matmul-only,
  matmul + GELU, full FFN block, attention-only, end-to-end BERT layer).
- **Per-backend timing harness** — measures each pattern across
  Device::Cpu / Metal / Mlx / Cuda / Rocm / Wgpu / Tpu / Fpga
  (whichever are enabled), reports p50 / p95 / GFLOP/s.
- **GPU thermal watchdog + `rlx-gpu` monitor/control** — every timed run
  records `gpu_peak` (peak temp/power) on `BenchResult`, and the `rlx-gpu`
  bin reads live NVIDIA/AMD telemetry and, as root, sets power caps /
  locked clocks / fan. See [GPU monitor & control]#gpu-monitor--control-rlx-gpu.
- **Examples**:
  - `bench_all` — sweep every (pattern × device × policy) cell.
  - `bench_autodiff` — measure reverse-mode AD overhead per op.
  - `bench_nth_order` — 3rd-order `sum(x³)` vs vector width N; all backends.
  - `bench_fft` — batch × N sweep across backends; set
    `RLX_BENCH_DISPATCH_ONLY=1` on wgpu to skip readback and isolate
    dispatch time.
  - `bench_fft_matrix` — full variant × precision × size × backend FFT/IFFT
    matrix with per-backend CPU-parity checks.
  - `bench_gguf_dequant` — per-scheme dequant + matmul sweep (CPU / Metal / WGPU /
    CUDA when enabled); use `just throttle` before timing runs.
  - `bench_mlx_wgpu` — matmul: `Device::Cpu` vs `Device::Mlx` (set
    `RLX_MLX_DEVICE=cpu` on Linux for MLX CPU path).
  - `bench_mlx_devices` — MLX device legs (Metal / Linux CPU / Linux CUDA);
    see [`docs/benchmarks/mlx-linux.md`]../../../docs/benchmarks/mlx-linux.md.
  - `bench_fk_fusion` — FKL resize prologue + batch region vs primitives;
    `FK_BENCH_OPS=1` prints fused op counts; `RLX_FK_BATCH_SINGLE_KERNEL=1`
    (CUDA/ROCm/Metal/wgpu) uses one batch-region launch; TPU uses per-slice HLO.
    See [`docs/fk-fusion.md`]../../../docs/fk-fusion.md.

Cross-platform results: [`docs/benchmarks/higher-order-ad.md`](../../../docs/benchmarks/higher-order-ad.md).

Linux MLX (compile, `RLX_MLX_DEVICE`, vs `rlx-cpu`): [`docs/benchmarks/mlx-linux.md`](../../../docs/benchmarks/mlx-linux.md).

## Install

```toml
[dependencies]
rlx-bench = "0.2"
```

## FFT benchmark

```sh
just throttle
cargo run -p rlx-bench --release --example bench_fft --features metal,gpu
RLX_BENCH_DISPATCH_ONLY=1 cargo run -p rlx-bench --release --example bench_fft --features gpu
./scripts/bench_fft_rig.sh   # remote CUDA rig (Windows + WSL)
```

`bench_fft_matrix` is the comprehensive harness: every variant (fft / ifft /
rfft) × precision (f32 / f64 / c64) × size × backend, with a per-backend
CPU-parity check per cell (use `--features metal,gpu,mlx,coreml,native-gpu-fft`
locally, or `cuda,gpu,native-gpu-fft` on a CUDA host). Focused perf A/Bs:
`bench_fft_cpu_parallel` (rayon batch scaling), `bench_fft_cpu_radix4`
(radix-2 vs radix-4), `bench_fft_stft_batch` (per-frame vs batched STFT),
`bench_fft_wgpu_multirow`, `bench_fft_backends` (cross-backend matrix).

## Run

```sh
cargo run -p rlx-bench --release --example bench_all
cargo run -p rlx-bench --release --example bench_nth_order --features metal,mlx,gpu,cuda
RLX_MLX_DEVICE=cpu cargo run -p rlx-bench --release --example bench_mlx_wgpu --features mlx
./rig.sh bench-nth-order both
./rig.sh bench-mlx-devices wsl
```

## GPU monitor & control (`rlx-gpu`)

`rlx-gpu` reads live GPU temperature / power / clock / fan telemetry and,
as root, sets the thermal knobs — a hardware tool built on
`rlx_runtime::device_thermal` and the per-vendor `rlx_cuda::nvml` (NVML) /
`rlx_rocm::rsmi` (ROCm-SMI) `libloading` shims. Build with the matching
backend feature to reach hardware; without one it prints an empty inventory.

```sh
# Monitor (read-only, unprivileged)
cargo run -p rlx-bench --bin rlx-gpu --features rocm -- --watch
cargo run -p rlx-bench --bin rlx-gpu --features cuda -- --device cuda --json

# Control (needs root): power cap (both vendors), locked clocks (NVIDIA),
# fan %; each has a --reset-* counterpart. Values are validated against the
# device's reported range.
sudo rlx-gpu --device rocm --index 0 --power-cap 200
sudo rlx-gpu --device cuda --index 0 --lock-clocks 1500
```

Every reading is best-effort: a sensor the board doesn't expose stays blank
rather than reporting a fake value (laptop GPUs omit the junction sensor and
a settable cap; APUs report socket power only). Control returns a typed
`ThermalError` — `PermissionDenied` without root, `Unsupported` where the
board rejects a knob (e.g. ROCm clock-lock, which is not wired — use the
power cap on discrete AMD parts), `OutOfRange` outside the valid envelope.

The timing harness also samples the backing GPU around each timed loop and
attaches the peak as `gpu_peak` to `BenchResult`, so a run whose wall-clock
was silently inflated by thermal throttling is visible.

## License

MIT OR Apache-2.0.