Skip to content

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

Merged
maleadt merged 1 commit into
mainfrom
tb/host-leaks
Nov 3, 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.

CUDA already marked its runtime in #3249 and host_leaks(CUDACore) was empty, so this is mostly for coherence with the other back ends:

  • @device_override, @device_function and @device_functions are one-liners around GPUToolbox.Overlays.device_override / device_function (which accepts blocks); ExprTools is no longer needed.
  • finish_module! looks up initialize_rng_state through the job's method tables and calls it as a void function, instead of inferring its return type with the native interpreter, which on 1.11 left native code instances of it behind. initialize_rng_state is now a device function.
  • A host leaks test next to the method table tests checks that GPUToolbox.Overlays.host_leaks(CUDACore) stays empty.
  • The compile-all test no longer sees the CPU stubs, which GPUToolbox now emits, so its sanity bound drops from 100 to 50 compiled methods (99 remain on 1.10).

Tested locally on an RTX 5080 with Julia 1.13 (device, exceptions, codegen, execution, KernelAbstractions and KernelInterface tests) and 1.10.

@github-actions

github-actions Bot commented Oct 29, 2026 •

Copy link
Copy Markdown
Contributor

Benchmark results

Compared with 4eb6468cd, the merge base.
The environment differs from the baseline's: BFloat16sExt 10.4.2 → 10.4.3, LLVM 10.4.2 → 10.4.3.

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 +1.2% 1 0 79
Latency −0.2% 0 0 3
Applications +0.0% 0 0 6
Benchmark Baseline This PR Change
Performance
cuda/synchronization/context/nonblocking 4.86 µs 7.35 µs +51.3% 🔴 slower
All benchmarks
Benchmark Baseline This PR Change
Performance
array/accumulate/Float32/1d 40.2 µs 39.8 µs −0.8%
array/accumulate/Float32/dims=1 28.2 µs 28.1 µs −0.4%
array/accumulate/Float32/dims=1L 82.9 µs 82.5 µs −0.4%
array/accumulate/Float32/dims=2 46.8 µs 47.1 µs +0.6%
array/accumulate/Float32/dims=2L 366 µs 364 µs −0.5%
array/accumulate/Int64/1d 66.7 µs 66.5 µs −0.3%
array/accumulate/Int64/dims=1 45.8 µs 45.8 µs +0.1%
array/accumulate/Int64/dims=1L 141 µs 141 µs +0.0%
array/accumulate/Int64/dims=2 67.0 µs 67.2 µs +0.3%
array/accumulate/Int64/dims=2L 760 µs 761 µs +0.0%
array/broadcast 9.24 µs 9.34 µs +1.0%
array/broadcast launch 5.60 µs 5.69 µs +1.6%
array/construct 1.38 µs 1.32 µs −4.4%
array/copy 17.2 µs 17.0 µs −1.1%
array/copyto!/cpu_to_gpu 207 µs 207 µs −0.1%
array/copyto!/gpu_to_cpu 240 µs 240 µs −0.0%
array/copyto!/gpu_to_gpu 8.90 µs 8.74 µs −1.8%
array/iteration/findall/bool 46.3 µs 47.9 µs +3.3%
array/iteration/findall/int 58.1 µs 58.4 µs +0.5%
array/iteration/findfirst/bool 31.2 µs 32.0 µs +2.5%
array/iteration/findfirst/int 31.5 µs 32.0 µs +1.7%
array/iteration/findmin/1d 48.7 µs 49.0 µs +0.7%
array/iteration/findmin/2d 37.8 µs 37.8 µs +0.0%
array/iteration/logical 46.9 µs 48.4 µs +3.3%
array/iteration/scalar 60.4 µs 60.1 µs −0.6%
array/permutedims/2d 45.4 µs 45.3 µs −0.3%
array/permutedims/3d 43.0 µs 43.1 µs +0.2%
array/permutedims/4d 36.1 µs 36.2 µs +0.4%
array/random/rand!/Float32 8.20 µs 8.23 µs +0.4%
array/random/rand!/Int64 14.3 µs 14.3 µs +0.3%
array/random/rand/Float32 11.3 µs 11.7 µs +3.0%
array/random/rand/Int64 18.7 µs 18.7 µs −0.1%
array/random/randn!/Float32 24.7 µs 24.7 µs −0.2%
array/random/randn/Float32 33.2 µs 33.1 µs −0.2%
array/reductions/mapreduce/Float32/1d 29.5 µs 30.0 µs +1.6%
array/reductions/mapreduce/Float32/dims=1 16.2 µs 16.7 µs +3.0%
array/reductions/mapreduce/Float32/dims=1L 54.0 µs 54.0 µs −0.0%
array/reductions/mapreduce/Float32/dims=2 23.8 µs 24.1 µs +1.2%
array/reductions/mapreduce/Float32/dims=2L 54.8 µs 54.4 µs −0.6%
array/reductions/mapreduce/Int64/1d 29.7 µs 29.5 µs −0.7%
array/reductions/mapreduce/Int64/dims=1 18.3 µs 18.7 µs +2.4%
array/reductions/mapreduce/Int64/dims=1L 93.1 µs 93.0 µs −0.1%
array/reductions/mapreduce/Int64/dims=2 24.7 µs 24.9 µs +0.9%
array/reductions/mapreduce/Int64/dims=2L 79.7 µs 79.7 µs +0.0%
array/reductions/reduce/Float32/1d 29.5 µs 29.8 µs +0.9%
array/reductions/reduce/Float32/dims=1 16.3 µs 16.6 µs +1.5%
array/reductions/reduce/Float32/dims=1L 53.9 µs 54.0 µs +0.1%
array/reductions/reduce/Float32/dims=2 24.0 µs 24.3 µs +1.5%
array/reductions/reduce/Float32/dims=2L 54.4 µs 54.4 µs −0.1%
array/reductions/reduce/Int64/1d 29.4 µs 30.2 µs +2.8%
array/reductions/reduce/Int64/dims=1 18.0 µs 18.3 µs +1.7%
array/reductions/reduce/Int64/dims=1L 92.8 µs 92.9 µs +0.1%
array/reductions/reduce/Int64/dims=2 24.7 µs 25.1 µs +1.7%
array/reductions/reduce/Int64/dims=2L 79.8 µs 79.5 µs −0.4%
array/reverse/1d 18.2 µs 18.7 µs +2.6%
array/reverse/1d_inplace 10.8 µs 11.1 µs +3.0%
array/reverse/1dL 72.0 µs 72.7 µs +1.0%
array/reverse/1dL_inplace 69.1 µs 69.3 µs +0.3%
array/reverse/2d 20.6 µs 20.9 µs +1.3%
array/reverse/2d_inplace 13.4 µs 13.6 µs +1.7%
array/reverse/2dL 79.0 µs 79.4 µs +0.5%
array/reverse/2dL_inplace 69.4 µs 69.7 µs +0.5%
array/sorting/1d 656 µs 657 µs +0.1%
array/sorting/2d 197 µs 197 µs +0.2%
array/sorting/by 802 µs 804 µs +0.2%
cuda/graph/capture 24.9 µs 25.1 µs +0.8%
cuda/graph/eager 24.6 µs 24.9 µs +1.5%
cuda/graph/launch 13.9 µs 14.0 µs +0.6%
cuda/synchronization/context/auto 2.08 µs 2.19 µs +5.3%
cuda/synchronization/context/blocking 919 ns 906 ns −1.5%
cuda/synchronization/context/nonblocking 4.86 µs 7.35 µs +51.3% 🔴 slower
cuda/synchronization/stream/auto 846 ns 839 ns −0.9%
cuda/synchronization/stream/blocking 786 ns 786 ns +0.0%
cuda/synchronization/stream/nonblocking 7.26 µs 7.31 µs +0.7%
kernel/indexing 10.3 µs 10.5 µs +2.1%
kernel/indexing_checked 10.8 µs 10.9 µs +0.5%
kernel/launch 1.33 µs 1.34 µs +0.8%
kernel/occupancy 30.0 ns 30.0 ns +0.0%
kernel/rand 13.8 µs 14.1 µs +2.7%
Latency
import 3.55 s 3.50 s −1.4%
precompile 5.43 s 5.44 s +0.3%
ttfp 4.01 s 4.03 s +0.5%
Applications
byval/reference 147 µs 147 µs +0.1%
byval/slices=1 147 µs 147 µs −0.0%
byval/slices=2 289 µs 289 µs +0.0%
byval/slices=3 431 µs 431 µs −0.0%
cudadevrt 104 µs 104 µs +0.1%
volumerhs 9.68 ms 9.67 ms −0.1%

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

@maleadt
maleadt force-pushed the tb/host-leaks branch 2 times, most recently from f477371 to 4ed1edd Compare October 30, 2026 14:17
`@device_override`, `@device_function` and `@device_functions` now forward
to `GPUToolbox.Overlays`, which implements the same rewrite (including the
docstring and block handling) for all back ends, so ExprTools is no longer
needed. `initialize_rng_state` becomes a device function, and
`finish_module!` looks it up in the job's method tables and calls it as a
void function instead of inferring its return type on the host.

CUDACore already has no device code that sysimage builds would compile
for the host; a test with `GPUToolbox.Overlays.host_leaks` keeps it that
way.

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

codecov Bot commented Nov 3, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 85.71%. Comparing base (4eb6468) to head (8a12729).
⚠️ Report is 1 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #3502      +/-   ##
==========================================
- Coverage   88.51%   85.71%   -2.80%     
==========================================
  Files         198      197       -1     
  Lines       22021    21734     -287     
==========================================
- Hits        19491    18629     -862     
- Misses       2530     3105     +575     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@maleadt
maleadt merged commit bf31227 into main Nov 3, 2026
18 checks passed
@maleadt
maleadt deleted the tb/host-leaks branch November 3, 2026 12: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