◆ FORGE Suite
GitHubMechanical Neuroimaging Lab · Univ. of Delaware
Skip to content

Set Up GPU Acceleration

This guide shows you how to enable GPU acceleration for the zone decomposition inverse solver: CUDA on NVIDIA hardware (full GPU offload) or Metal on Apple Silicon (GPU gradient kernel plus batched CPU line search). If you are still deciding whether a GPU will help your problem, see GPU Backends and When They Help first.

NVIDIA GPUs (CUDA)

Requirements

ComponentVersionPurpose
NVIDIA GPUCompute capability 7.0+Hardware
CUDA toolkit12.0+Runtime/drivers
CUDA.jl5.0+Julia GPU arrays, kernel launch
CUDSS.jl0.6+GPU sparse direct solver (cuDSS)

Install and load

julia
using Pkg
Pkg.add(["CUDA", "CUDSS"])

Loading both packages alongside Sentinel activates the SentinelCUDAExt package extension, which registers the GPU solver types:

julia
using CUDA, CUDSS
using Sentinel

Run a GPU-accelerated inversion

Pass a CUDSSBatchedSolver and a CUDA gradient backend to run_inverse_solve!:

julia
prob  = load_inversion("runfile.dat")
setup = setup_inverse_problem(prob, data_dir)

material, disp, state = run_inverse_solve!(setup;
    solver=CachedDirectSolver(),
    gradient_backend=KAGradientBackend(CUDABackend()),
    cudss_batched_solver=CUDSSBatchedSolver(structure="G"),
    verbose=true)

This accelerates all three phases of the batched driver: the forward and adjoint solves (batched cuDSS factorization), the gradient kernel, and the line search (per-zone cuDSS solvers on isolated CUDA streams). Refer to the CUDA Backend reference for the solver types and their memory behaviour.

Apple Silicon (Metal)

Requirements

  • Apple Silicon Mac (M1 or later)

  • Julia 1.11+

  • Metal.jl

Install and load

julia
using Pkg
Pkg.add("Metal")
julia
using Metal
using Sentinel

Loading Metal alongside Sentinel activates the SentinelMetalExt extension. On macOS Sentinel also loads AppleAccelerate automatically — no configuration is needed for that.

Run a GPU-accelerated inversion

Metal accelerates the gradient kernel only; linear solves stay on the CPU in Float64 (see GPU Backends and When They Help for why). Pass a Metal gradient backend, and a CPUBatchedSolver to enable the batched line search — the bulk of the Apple-Silicon speedup:

julia
material, disp, state = zone_decomposition_solve_batched_gpu!(
    material, grid, dh, gp2mtrs, meshes, meas, bcs, model, omega, rho, config;
    solver=CachedDirectSolver(),
    gradient_backend=KAGradientBackend(MetalBackend()),
    cudss_batched_solver=CPUBatchedSolver())  # keyword name is historical — no CUDA involved

See Run Inversions in Parallel for the batched driver phases and Tune Performance for measured timings on Apple Silicon.

Troubleshooting

CUDA out of memory / ERROR_ILLEGAL_ADDRESS

If the solver crashes with ERROR_ILLEGAL_ADDRESS after many iterations, GPU memory is likely exhausted. The driver's inter-iteration garbage collection should handle this automatically; if the problem persists:

  1. Reduce the thread count (fewer concurrent CUDSSDirectSolver instances during line search).

  2. Verify GC.gc() runs between global iterations.

  3. Monitor GPU memory with CUDA.memory_status().

All concurrent cuDSS operations must use separate CUDA streams. Each CUDSSDirectSolver constructs its own stream by default; if you see intermittent wrong results or crashes, make sure a single solver instance is not being shared across threads.