When gpu-offload is excellent, when it does nothing, and when not to use it

Short version: it pays when a program spends most of its time in a few large dense linear-algebra calls, and it does nothing for everything else. It is built to do nothing rather than make things slower, but there are cases where you should not use it at all.

Decide in five minutes

gpu-offload measure  your-command     # how much of the run time is offloadable math?
gpu-offload calibrate                 # once: where does this machine's GPU win?
gpu-offload estimate TRACE_DIR        # predicted saving at every level
gpu-offload run --verify your-command # do GPU and CPU results agree on your data?

If measure shows less than about a third of the run time in calls of 1 ms or longer, stop here: no offloading tool can help much, because the rest of the program is not offloadable.

Excellent fit

Situation Why it works Evidence from the experiments
Large symmetric eigenproblems (numpy.linalg.eigh, eigvalsh, PCA via eigendecomposition), n from about 1000 up The GPU solver is several times faster even in float64, and the copy is small compared with the work eigenvectors, float64: 2.3x at n=1024, 3.7x at n=4096, 6.2x at n=8192; eigh at n=6000 took 2.27 s on the GPU against a predicted 11.1 s on the CPU
Large singular value problems (values only) Same reason float64: 6.9x at n=4096, 21.1x at n=8192
Single-precision or complex-single dense algebra, n from about 2000 up Consumer GPUs are strong in float32 float32 matrix product 2.7x at n=4096 and 4.7x at n=8192; float32 linear solve 6.4x at n=4096; complex64 linear solve 11.9x at n=4096
Programs you cannot or do not want to modify No source, no build system, a vendor binary, a script you only run Works on unmodified NumPy, R, Octave programs; no code was changed in any workload
Machines where the CPU math library is weak or badly configured The profile reflects the CPU as it really behaves With OpenBLAS’s default thread count the same workloads ran 15 to 25 times slower on the CPU
Mixed workloads on a shared workstation Small calls stay on the CPU, the GPU is only started when it pays, and it backs off when other programs use the GPU Programs with nothing to offload ran unchanged

Expect whole-program gains of the order measured here: 1.5x to 1.7x on linear-algebra-heavy scripts at n=6000 (median of 3 runs). The gain is capped by the share of the program that is offloadable math.

Works, but with little or no gain

Situation Why What you will see
Double-precision matrix products, triangular solves, Cholesky on a consumer GPU with a strong CPU Consumer GPUs are slow in float64; a modern 16-core CPU matches or beats them “stayed on the CPU, predicted gain too small”; float64 gemm was never faster on the RTX 5080 (0.8x at n=8192)
Small and medium problems (roughly n below 1000) Copying data and launching GPU kernels costs more than the work Calls stay on the CPU
Many tiny calls (scikit-learn k-means made 467,664 products of size 16 x 256 x 30; small neural-network layers) No single call is large enough; the work is in the number of calls Nothing offloaded
Short programs The GPU start-up cost (0.3 to 1.9 s measured) is never repaid “GPU start-up not yet worth it”
Data pipelines (pandas), FFT with NumPy, text processing, I/O-bound work They do not call BLAS / LAPACK 0% of run time interceptable in the pandas and NumPy-FFT workloads
R’s lm(), element-wise array math Level-1 BLAS on long vectors and plain loops: too little work per byte moved Not offloaded

In these cases gpu-offload costs almost nothing (about 15 ns per intercepted call that stays on the CPU) and changes nothing. A higher level will offload more of the borderline calls for a small gain or loss.

Do not use it

Situation Reason
You need bit-identical results to a CPU run GPU floating-point operations run in a different order. Results agree to rounding (largest relative difference 1.2e-06 in float32 in the tests), not bit for bit. Eigenvectors and singular vectors may differ in sign.
Safety-critical, regulated or otherwise high-assurance computation It is a v0.1 prototype tested on one machine.
Production services No system-wide daemon, no persistence of what it learns between runs, opt-in per command.
Programs you can easily port to a GPU library CuPy, PyTorch, RAPIDS or JAX keep data on the GPU between operations. gpu-offload copies data in and out on every call, so a native GPU program is faster.
Programs that fork() workers after doing GPU work The children stay on the CPU (a CUDA context does not survive fork()). Harmless, but there is no gain in the workers.
Security-sensitive processes, set-uid programs, anti-cheat or DRM-protected software It injects a library with LD_PRELOAD. Do not put it into processes that must not be instrumented.
No NVIDIA GPU, or macOS / native Windows Only a CUDA backend exists, on Linux (WSL2 included).
Problems larger than GPU memory They fall back to the CPU; there is no out-of-core path.

Hardware changes the answer

The table that matters is the one gpu-offload status prints on your machine. Two examples of how it shifts:

  • A data-centre GPU with full-speed float64 (instead of a consumer card) would move the double-precision rows from “never” to a clear win.
  • A laptop CPU (instead of a 16-core desktop CPU) lowers every CPU curve, so the GPU wins at smaller sizes.

Neither was measured here. Calibrating is how you find out.

Known rough edges

  • Calibration on a busy machine is noisy. The calibrator waits for quiet moments and repeats disturbed points, and the run-time CPU probes correct what remains, but a profile taken while other heavy jobs run will be less accurate. Calibrate when the machine is otherwise idle.
  • Timings of whole programs varied by 20 to 30 percent between runs on the development machine, which was shared with other virtual machines. Compare medians of several runs.
  • The first GPU call of each kind includes a one-off warm-up inside the CUDA libraries (83 to 262 ms was observed). Long-running programs do not notice; very short ones do.

Copyright 2026 Jaifar Alshizawi. gpu-offload is open source under the GNU AGPL v3; a commercial licence is available. Contributions are welcome.

This site uses Just the Docs, a documentation theme for Jekyll.