Skip to content

Define device-only functions as overlays, so sysimages load - #1205

Merged
maleadt merged 1 commit into
mainfrom
tb/host-leaks
Oct 30, 2026
Merged

maleadt merged 1 commit into
mainfrom
tb/host-leaks

Conversation

@maleadt

@maleadt maleadt commented Oct 28, 2026

Copy link
Copy Markdown
Member

Device-only code in the global method table gets compiled for the host by sysimage builds: Julia 1.12+ compiles every method with a compileable signature, and 1.11 keeps native code instances (e.g. those left by Core.Compiler.return_type(initialize_rng_state) in finish_module!). The image then refers to device symbols like julia.gpu.state_getter, and since sysimages are loaded with RTLD_NOW, it fails to load. Same fix as JuliaGPU/KernelAbstractions.jl#930 and JuliaGPU/OpenCL.jl#598, using the shared definitions from GPUToolbox 3.5.

  • @device_override and @device_function are one-liners around GPUToolbox.Overlays.device_override / device_function; ExprTools is no longer needed.
  • What GPUToolbox.Overlays.host_leaks(AMDGPU) reported is now a device function: output_context, printf_output_context, malloc_hc, free_hc, signal_exception, malloc, free (julia.gpu.state_getter), and ROCKernels' hardware_lane and lane_id (llvm.amdgcn.mbcnt.lo). Also kernel_state, which compile-all skips as a generated function, but which is the source of these. The KernelInterface functions built on the lane helpers already were @device_overrides.
  • malloc and free lose their return type annotations, which Julia 1.10's @overlay can't parse; malloc asserts its result type instead.
  • A new core/host_leaks test checks that host_leaks is empty for AMDGPU and its extensions.

Tested locally on a gfx1036 with Julia 1.13 (core, device, KernelAbstractions and KernelInterface tests) and 1.10.

… host images

Sysimage builds compile methods from the global method table for the host
(every compileable signature on Julia 1.12+), so device-only code there ends
up in the image as references to `julia.gpu.state_getter` or AMDGPU LLVM
intrinsics, and the image then fails to load.

Implement `@device_override` and `@device_function` with GPUToolbox's
`Overlays`, dropping the ExprTools dependency, and mark the runtime functions
that read the kernel state (`kernel_state`, the hostcall contexts,
`signal_exception`, `malloc` and `free`) and ROCKernels' lane helpers as
device functions. Their host methods now only throw. `malloc` and `free` lose
their return type annotations, which Julia 1.10's `@overlay` can't handle.
A new test checks with `GPUToolbox.Overlays.host_leaks` that no host-compiled
method reaches device code.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown
Contributor

Benchmark results

Compared with 6ecd201bb, the merge base.
Times are the minimum time of every benchmark. A change is unusual when it exceeds both three times the benchmark's typical change between consecutive runs on the default branch and a minimum per category (performance 3%, latency 5%, applications 3%, other 3%). A benchmark that starts or stops allocating is listed however few the allocations. A single run can still be a fluke, so rerun before drawing conclusions.

Geometric mean Unusual: slower Unusual: faster Compared
Performance −0.6% 3 2 69
Latency +1.1% 0 0 3
Applications −1.0% 0 0 14
Benchmark Baseline This PR Change
Performance
array/permutedims/4d 50.2 µs 41.1 µs −18.3% 🟢 faster
array/reductions/reduce/Float32/1d 69.3 µs 58.0 µs −16.4% 🟢 faster
array/reductions/mapreduce/Float32/1d 58.7 µs 67.7 µs +15.4% 🔴 slower
array/copy 33.3 µs 38.1 µs +14.3% 🔴 slower
array/reductions/reduce/Float32/dims=2 46.1 µs 52.6 µs +14.1% 🔴 slower
All benchmarks
Benchmark Baseline This PR Change
Performance
amdgpu/synchronization/context/device 1.72 µs 1.79 µs +4.4%
amdgpu/synchronization/stream/blocking 233 ns 230 ns −1.1%
amdgpu/synchronization/stream/nonblocking 343 ns 353 ns +2.9%
array/accumulate/Float32/1d 79.3 µs 78.7 µs −0.7%
array/accumulate/Float32/dims=1 63.2 µs 62.4 µs −1.3%
array/accumulate/Float32/dims=1L 105 µs 104 µs −0.3%
array/accumulate/Float32/dims=2 103 µs 101 µs −1.2%
array/accumulate/Float32/dims=2L 116 µs 116 µs −0.4%
array/accumulate/Int64/1d 101 µs 101 µs −0.6%
array/accumulate/Int64/dims=1 74.0 µs 73.5 µs −0.6%
array/accumulate/Int64/dims=1L 93.6 µs 108 µs +15.4%
array/accumulate/Int64/dims=2 106 µs 105 µs −0.7%
array/accumulate/Int64/dims=2L 146 µs 143 µs −1.8%
array/broadcast 21.7 µs 21.6 µs −0.9%
array/construct 2.06 µs 2.01 µs −2.3%
array/copy 33.3 µs 38.1 µs +14.3% 🔴 slower
array/copyto!/cpu_to_gpu 83.8 µs 83.9 µs +0.1%
array/copyto!/gpu_to_cpu 83.7 µs 83.7 µs −0.0%
array/copyto!/gpu_to_gpu 24.9 µs 24.5 µs −1.7%
array/iteration/findall/bool 90.8 µs 90.2 µs −0.6%
array/iteration/findall/int 102 µs 101 µs −0.5%
array/iteration/findfirst/bool 56.1 µs 54.9 µs −2.2%
array/iteration/findfirst/int 54.1 µs 55.9 µs +3.4%
array/iteration/findmin/1d 91.0 µs 91.4 µs +0.4%
array/iteration/findmin/2d 75.4 µs 76.1 µs +1.0%
array/iteration/logical 86.1 µs 86.4 µs +0.3%
array/iteration/scalar 304 µs 296 µs −2.4%
array/permutedims/2d 57.7 µs 56.5 µs −2.1%
array/permutedims/3d 55.7 µs 55.2 µs −0.9%
array/permutedims/4d 50.2 µs 41.1 µs −18.3% 🟢 faster
array/random/rand!/Float32 23.7 µs 23.3 µs −1.5%
array/random/rand!/Int64 24.6 µs 27.0 µs +9.8%
array/random/rand/Float32 42.3 µs 41.8 µs −1.2%
array/random/rand/Int64 43.3 µs 42.7 µs −1.3%
array/random/randn!/Float32 30.5 µs 30.4 µs −0.6%
array/random/randn/Float32 68.9 µs 68.7 µs −0.3%
array/reductions/mapreduce/Float32/1d 58.7 µs 67.7 µs +15.4% 🔴 slower
array/reductions/mapreduce/Float32/dims=1 51.8 µs 51.3 µs −1.0%
array/reductions/mapreduce/Float32/dims=1L 56.0 µs 55.0 µs −1.7%
array/reductions/mapreduce/Float32/dims=2 54.7 µs 54.1 µs −1.1%
array/reductions/mapreduce/Float32/dims=2L 67.7 µs 67.2 µs −0.7%
array/reductions/mapreduce/Int64/1d 70.0 µs 68.4 µs −2.3%
array/reductions/mapreduce/Int64/dims=1 48.1 µs 47.6 µs −1.0%
array/reductions/mapreduce/Int64/dims=1L 67.0 µs 66.7 µs −0.6%
array/reductions/mapreduce/Int64/dims=2 55.3 µs 55.0 µs −0.6%
array/reductions/mapreduce/Int64/dims=2L 73.1 µs 71.3 µs −2.5%
array/reductions/reduce/Float32/1d 69.3 µs 58.0 µs −16.4% 🟢 faster
array/reductions/reduce/Float32/dims=1 52.2 µs 50.5 µs −3.1%
array/reductions/reduce/Float32/dims=1L 55.7 µs 55.1 µs −1.0%
array/reductions/reduce/Float32/dims=2 46.1 µs 52.6 µs +14.1% 🔴 slower
array/reductions/reduce/Float32/dims=2L 67.5 µs 67.0 µs −0.7%
array/reductions/reduce/Int64/1d 69.6 µs 68.0 µs −2.3%
array/reductions/reduce/Int64/dims=1 48.1 µs 47.6 µs −1.1%
array/reductions/reduce/Int64/dims=1L 66.8 µs 66.1 µs −1.1%
array/reductions/reduce/Int64/dims=2 55.2 µs 54.7 µs −0.9%
array/reductions/reduce/Int64/dims=2L 72.7 µs 72.3 µs −0.5%
array/reverse/1d 40.6 µs 39.2 µs −3.4%
array/reverse/1d_inplace 27.6 µs 23.3 µs −15.6%
array/reverse/1dL 64.2 µs 65.0 µs +1.2%
array/reverse/1dL_inplace 30.9 µs 30.4 µs −1.4%
array/reverse/2d 41.0 µs 42.2 µs +2.9%
array/reverse/2d_inplace 26.4 µs 26.1 µs −1.0%
array/reverse/2dL 70.8 µs 69.7 µs −1.6%
array/reverse/2dL_inplace 36.1 µs 34.5 µs −4.3%
array/sorting/1d 294 µs 294 µs +0.2%
kernel/indexing 20.5 µs 20.2 µs −1.4%
kernel/indexing_checked 25.0 µs 24.5 µs −2.3%
kernel/launch 788 ns 793 ns +0.6%
kernel/rand 28.4 µs 27.8 µs −2.1%
Latency
import 1.27 s 1.31 s +3.2%
precompile 28.6 s 28.4 s −0.6%
ttfp 1.69 s 1.71 s +0.9%
Applications
bitonic_sort 1.05 ms 1.05 ms −0.0%
byval/reference 39.9 µs 39.4 µs −1.3%
byval/slices=1 39.9 µs 40.4 µs +1.1%
byval/slices=2 158 µs 144 µs −8.9%
byval/slices=3 228 µs 230 µs +0.7%
convolution 52.4 µs 52.2 µs −0.3%
floyd_warshall 8.94 ms 8.92 ms −0.2%
gemm/tiled 2.61 ms 2.60 ms −0.3%
gemm/tiled_unbounded 2.60 ms 2.60 ms +0.2%
histogram 754 µs 740 µs −1.8%
prefix_sum 194 µs 189 µs −2.2%
stencil/diffusion3d 1.55 ms 1.56 ms +0.1%
stencil/diffusion3d_checked 1.59 ms 1.60 ms +0.2%
volumerhs 4.84 ms 4.83 ms −0.2%

History: https://juliagpu.org/perf/?pkg=amdgpu

@maleadt
maleadt merged commit 3471645 into main Oct 30, 2026
11 checks passed
@maleadt
maleadt deleted the tb/host-leaks branch October 30, 2026 09:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant