Backend conventions
SkillDev toolsHow JustRelax.jl handles CPU/CUDA/AMDGPU backends — module structure, package extensions, ParallelStencil initialization rules. Use when adding/modifying kernels or anything device-related.
Available today. Use it from your connected AI after setup.
No other account needed.
Connect ahel once, and every AI you use reads what you have installed.
Then ask your AI: use the Backend conventions skill
What this skill tells your AI
The instructions your AI receives, as published by ptsolvers/justrelax.jl in .claude/skills/backend-conventions/SKILL.md and read by ahel’s review.
Structure
src/JustRelax.jl— top-level module: types, traits (BackendTrait,CPUBackendTrait, ...),CPUBackend/CUDABackend/AMDGPUBackendsingletons,PTArray.src/JustRelax_CPU.jl— definesJustRelax2DandJustRelax3Dsubmodules (the CPU implementations). Each calls@init_parallel_stencil(Threads, Float64, N)in its__init__.ext/JustRelaxCUDAExt.jl,ext/JustRelaxAMDGPUExt.jl— package extensions (weakdeps in Project.toml). They mapPTArray(::Type{CUDABackend}) = CuArray, define backend traits, and include the device versions of the 2D/3D modules fromsrc/ext/CUDA/andsrc/ext/AMDGPU/.ext/JustRelaxMakieExt.jl— plotting extension.
Key rules
- Solver code is written once in
src/using ParallelStencil macros; the GPU extensions re-include shared code with a different@init_parallel_stencil. A change to solver logic insrc/must work on all backends — check whether the file is included fromsrc/ext/CUDA/2D.jletc. too. - ParallelStencil's
@init_parallel_stencilis once per module per session. Switching backend or dimensionality requires a fresh Julia process. Never try to re-init in the same session. - User-facing scripts/tests select the backend via
ENV["JULIA_JUSTRELAX_BACKEND"](CPU/CUDA/AMDGPU) and passbackend_JR(e.g.CPUBackend) to constructors likeStokesArrays(backend_JR, ni). JustPIC dispatches on KernelAbstractions backends —JustPIC.CPUon the host, andCUDA.CUDABackend/AMDGPU.ROCBackendon device (JustPIC binds neither vendor tag itself; its extensions do). These are different types from JustRelax's; don't mix them. - Dispatch on device is done via traits (
backend(::CuArray) = CUDABackendTrait()), not viaisa CuArraychecks. Follow that pattern. - MPI/halo exchange goes through ImplicitGlobalGrid (
IGG); CUDA-aware MPI is enabled in CI withIGG_CUDAAWARE_MPI=1.
Local environment
Before assuming which backends are available, check at runtime:
# Is a CUDA GPU present and functional?
using CUDA
CUDA.functional() # true → CUDA backend usable; false → no GPU or driver issue
# Is an AMD GPU present?
using AMDGPU
AMDGPU.functional() # analogous
The CPU (Threads) backend always works regardless of OS. GPU availability depends on hardware and drivers — don't assume a machine lacks a GPU based on OS alone (Windows/Linux with NVIDIA hardware is common in HPC and workstation setups). When CUDA.functional() returns false, fall back to CPU and note that GPU correctness is verified by the CSCS GH200 CUDA pipeline (ci/cscs-gh200.yml). Write GPU-safe code (see kernel-style) regardless, so changes are ready for CI validation.
Signals
- GitHub stars
- 44
- Forks
- 12
- Last commit
- Sep 2026
Advanced
- Catalog kind
- skill
- Gateway key
backend-conventions- Source
- github.com/ptsolvers/justrelax.jl