Skip to content

POCL: reduce launch memory allocations - #901

Merged
maleadt merged 4 commits into
mainfrom
mg/pocl-rm-launch-allocs
Oct 17, 2026
Merged

maleadt merged 4 commits into
mainfrom
mg/pocl-rm-launch-allocs

Conversation

@giordano

@giordano giordano commented Oct 16, 2026 •

Copy link
Copy Markdown
Collaborator

Launching a compiled kernel on the POCL back-end allocated 96 bytes, and waiting for it another 112 bytes when the wait involved a completion callback, which depends on how long the kernel takes and on host load. This made allocation tests of CPU kernels, as in Oceananigans (CliMA/Oceananigans.jl#5799, for the KA 0.10 compatibility), fail on busy machines. With this PR and GPUToolbox 3.4.1 (JuliaGPU/GPUToolbox.jl#32, fixing JuliaGPU/GPUToolbox.jl#31), launches allocate nothing on Julia 1.12 and 1.13:

  • compiler_config hashed its keyword arguments as Pairs, which boxes every value (16 bytes). Hash values(kwargs), like the other back-ends.
  • KI.kernel_function passed the device's sub-group width to clfunction, as nothing on devices without sub-groups, so the keyword call was dynamic (64 bytes). The default width is now determined with the compiler configuration, as in OpenCL.jl, and not passed at all. This also makes @opencl default to the device's width instead of 32 (which is the same on devices that support 32).
  • check is inlined, so that Refs passed to API calls can live on the stack, and so is the call to clEnqueueNDRangeKernel, whose Ref for the event was allocated on every launch (16 bytes).
  • GPUToolbox 3.4.1 is required, whose cooperative_wait no longer allocates on the completion-callback path.

Allocations per launch of the reproducer from JuliaGPU/GPUToolbox.jl#31:

0.10.0 this PR
short kernel 96 B 0 B
long kernel (callback) 208 B 0 B

The new tests check that compiler_config, clfunction, KI.kernel_function and launches of a short and a long kernel don't allocate. They're skipped where Julia still allocates: on 1.10, in GPUCompiler's lookup of compiled code and in waits on 1.11, and on 1.14, where GPUToolbox shields waits from task cancellation with a scoped value (and GPUCompiler allocates when looking up compiled code, see JuliaGPU/GPUCompiler.jl#1025).

Bumps the version to 0.10.1.

@giordano
giordano requested review from maleadt and vchuravy October 16, 2026 20:53
@giordano giordano added performance Runtime performance. pocl The PoCL-based CPU back-end. labels Oct 16, 2026
@github-actions

github-actions Bot commented Oct 16, 2026 •

Copy link
Copy Markdown
Contributor

Benchmark Results

Show table
main da38f0d... main / da38f0d...
const/@Const/Float32/262144 0.632 ± 0.022 ms 0.628 ± 0.016 ms 1.01 ± 0.043
const/@Const/Float32/65536 0.226 ± 0.014 ms 0.194 ± 0.016 ms 1.16 ± 0.12
const/@Const/Float64/262144 0.836 ± 0.02 ms 0.825 ± 0.02 ms 1.01 ± 0.035
const/@Const/Float64/65536 0.368 ± 0.013 ms 0.364 ± 0.012 ms 1.01 ± 0.049
const/unmarked/Float32/262144 2.35 ± 0.036 ms 2.32 ± 0.037 ms 1.02 ± 0.022
const/unmarked/Float32/65536 0.624 ± 0.019 ms 0.62 ± 0.023 ms 1.01 ± 0.048
const/unmarked/Float64/262144 3.11 ± 0.021 ms 3.12 ± 0.048 ms 0.996 ± 0.017
const/unmarked/Float64/65536 0.811 ± 0.022 ms 0.807 ± 0.012 ms 1.01 ± 0.031
dgsem/2D/Float32/fluxdiff/element 0.57 ± 0.019 ms 0.562 ± 0.03 ms 1.01 ± 0.063
dgsem/2D/Float32/fluxdiff/node E=8 0.787 ± 0.0077 ms 0.786 ± 0.021 ms 1 ± 0.028
dgsem/2D/Float32/fluxdiff/node halfsweep E=8 0.574 ± 0.013 ms 0.571 ± 0.019 ms 1.01 ± 0.04
dgsem/2D/Float32/fluxdiff/node halfsweep v-last E=8 0.594 ± 0.018 ms 0.592 ± 0.02 ms 1 ± 0.046
dgsem/2D/Float32/weak/element 0.203 ± 0.0026 ms 0.198 ± 0.0032 ms 1.03 ± 0.021
dgsem/2D/Float32/weak/element private 0.218 ± 0.015 ms 0.212 ± 0.014 ms 1.03 ± 0.096
dgsem/2D/Float32/weak/node localmem E=1 0.213 ± 0.027 ms 0.197 ± 0.026 ms 1.08 ± 0.2
dgsem/2D/Float32/weak/node localmem E=8 0.211 ± 0.0072 ms 0.182 ± 0.012 ms 1.16 ± 0.088
dgsem/2D/Float32/weak/node localmem v-last E=1 0.251 ± 0.019 ms 0.272 ± 0.012 ms 0.926 ± 0.082
dgsem/2D/Float32/weak/node localmem v-last E=8 0.25 ± 0.022 ms 0.247 ± 0.014 ms 1.01 ± 0.11
dgsem/2D/Float32/weak/node recompute E=8 0.503 ± 0.016 ms 0.509 ± 0.019 ms 0.987 ± 0.049
dgsem/2D/Float64/fluxdiff/element 0.605 ± 0.023 ms 0.598 ± 0.02 ms 1.01 ± 0.052
dgsem/2D/Float64/fluxdiff/node E=8 0.791 ± 0.026 ms 0.793 ± 0.02 ms 0.997 ± 0.041
dgsem/2D/Float64/fluxdiff/node halfsweep E=8 0.606 ± 0.02 ms 0.606 ± 0.018 ms 0.999 ± 0.045
dgsem/2D/Float64/fluxdiff/node halfsweep v-last E=8 0.636 ± 0.019 ms 0.619 ± 0.013 ms 1.03 ± 0.037
dgsem/2D/Float64/weak/element 0.242 ± 0.015 ms 0.232 ± 0.013 ms 1.04 ± 0.085
dgsem/2D/Float64/weak/element private 0.235 ± 0.015 ms 0.237 ± 0.013 ms 0.994 ± 0.084
dgsem/2D/Float64/weak/node localmem E=1 0.218 ± 0.026 ms 0.205 ± 0.026 ms 1.06 ± 0.18
dgsem/2D/Float64/weak/node localmem E=8 0.198 ± 0.028 ms 0.184 ± 0.0024 ms 1.08 ± 0.15
dgsem/2D/Float64/weak/node localmem v-last E=1 0.263 ± 0.015 ms 0.279 ± 0.021 ms 0.943 ± 0.089
dgsem/2D/Float64/weak/node localmem v-last E=8 0.254 ± 0.023 ms 0.253 ± 0.021 ms 1 ± 0.12
dgsem/2D/Float64/weak/node recompute E=8 0.645 ± 0.019 ms 0.643 ± 0.013 ms 1 ± 0.035
dgsem/3D/Float32/fluxdiff/element 1.93 ± 0.0075 ms 1.91 ± 0.01 ms 1.01 ± 0.0066
dgsem/3D/Float32/fluxdiff/node E=2 3.38 ± 0.03 ms 3.33 ± 0.055 ms 1.01 ± 0.019
dgsem/3D/Float32/fluxdiff/node halfsweep E=1 2.44 ± 0.034 ms 2.36 ± 0.011 ms 1.03 ± 0.015
dgsem/3D/Float32/fluxdiff/node halfsweep v-last E=1 2 ± 0.0059 ms 2 ± 0.024 ms 0.998 ± 0.012
dgsem/3D/Float32/weak/element 0.676 ± 0.013 ms 0.662 ± 0.013 ms 1.02 ± 0.028
dgsem/3D/Float32/weak/element private 0.7 ± 0.01 ms 0.689 ± 0.013 ms 1.02 ± 0.025
dgsem/3D/Float32/weak/node localmem E=1 0.674 ± 0.018 ms 0.679 ± 0.021 ms 0.993 ± 0.04
dgsem/3D/Float32/weak/node localmem E=2 0.74 ± 0.018 ms 0.75 ± 0.024 ms 0.987 ± 0.039
dgsem/3D/Float32/weak/node localmem v-last E=1 0.899 ± 0.028 ms 0.89 ± 0.0058 ms 1.01 ± 0.033
dgsem/3D/Float32/weak/node localmem v-last E=2 0.996 ± 0.021 ms 1.01 ± 0.035 ms 0.983 ± 0.04
dgsem/3D/Float32/weak/node recompute E=2 2.07 ± 0.0096 ms 2.09 ± 0.018 ms 0.99 ± 0.0097
dgsem/3D/Float32/weak/slab E=1 2.74 ± 0.032 ms 2.69 ± 0.012 ms 1.02 ± 0.013
dgsem/3D/Float32/weak/slab E=8 5.57 ± 0.016 ms 5.51 ± 0.045 ms 1.01 ± 0.0087
dgsem/3D/Float32/weak/slab double-buffered E=1 1.58 ± 0.023 ms 1.57 ± 0.015 ms 1 ± 0.018
dgsem/3D/Float32/weak/slab double-buffered E=8 2.02 ± 0.0058 ms 2 ± 0.0047 ms 1.01 ± 0.0038
dgsem/3D/Float32/weak/slab double-buffered v-last E=1 1.61 ± 0.012 ms 1.6 ± 0.0097 ms 1.01 ± 0.0098
dgsem/3D/Float32/weak/slab double-buffered v-last E=8 2.13 ± 0.0054 ms 2.09 ± 0.013 ms 1.02 ± 0.007
dgsem/3D/Float32/weak/slab v-last E=1 2.76 ± 0.011 ms 2.7 ± 0.013 ms 1.02 ± 0.0063
dgsem/3D/Float32/weak/slab v-last E=8 5.65 ± 0.016 ms 5.6 ± 0.041 ms 1.01 ± 0.0079
dgsem/3D/Float64/fluxdiff/element 1.97 ± 0.0054 ms 1.98 ± 0.0074 ms 0.992 ± 0.0046
dgsem/3D/Float64/fluxdiff/node E=2 2.98 ± 0.0085 ms 2.99 ± 0.011 ms 0.997 ± 0.0046
dgsem/3D/Float64/fluxdiff/node halfsweep E=1 2.19 ± 0.011 ms 2.22 ± 0.0079 ms 0.986 ± 0.0062
dgsem/3D/Float64/fluxdiff/node halfsweep v-last E=1 2.11 ± 0.0072 ms 2.14 ± 0.028 ms 0.986 ± 0.013
dgsem/3D/Float64/weak/element 0.822 ± 0.0081 ms 0.826 ± 0.016 ms 0.995 ± 0.022
dgsem/3D/Float64/weak/element private 0.848 ± 0.012 ms 0.846 ± 0.0035 ms 1 ± 0.015
dgsem/3D/Float64/weak/node localmem E=1 0.712 ± 0.02 ms 0.716 ± 0.021 ms 0.995 ± 0.041
dgsem/3D/Float64/weak/node localmem E=2 0.782 ± 0.018 ms 0.796 ± 0.014 ms 0.982 ± 0.028
dgsem/3D/Float64/weak/node localmem v-last E=1 0.905 ± 0.011 ms 0.892 ± 0.0048 ms 1.01 ± 0.014
dgsem/3D/Float64/weak/node localmem v-last E=2 1.02 ± 0.024 ms 1.01 ± 0.03 ms 1.01 ± 0.038
dgsem/3D/Float64/weak/node recompute E=2 2.22 ± 0.01 ms 2.22 ± 0.018 ms 1 ± 0.0094
dgsem/3D/Float64/weak/slab E=1 2.77 ± 0.043 ms 2.89 ± 0.01 ms 0.958 ± 0.015
dgsem/3D/Float64/weak/slab E=8 6.35 ± 0.028 ms 6.25 ± 0.019 ms 1.02 ± 0.0055
dgsem/3D/Float64/weak/slab double-buffered E=1 1.61 ± 0.026 ms 1.61 ± 0.011 ms 1 ± 0.018
dgsem/3D/Float64/weak/slab double-buffered E=8 2.12 ± 0.0092 ms 2.09 ± 0.0045 ms 1.01 ± 0.0049
dgsem/3D/Float64/weak/slab double-buffered v-last E=1 1.66 ± 0.0092 ms 1.65 ± 0.0096 ms 1.01 ± 0.0081
dgsem/3D/Float64/weak/slab double-buffered v-last E=8 2.22 ± 0.033 ms 2.13 ± 0.0085 ms 1.04 ± 0.016
dgsem/3D/Float64/weak/slab v-last E=1 2.73 ± 0.019 ms 2.79 ± 0.009 ms 0.979 ± 0.0074
dgsem/3D/Float64/weak/slab v-last E=8 6.19 ± 0.015 ms 6.17 ± 0.049 ms 1 ± 0.0083
launch/3D static workgroup, dynamic ndrange 10.8 ± 0.59 μs 10.5 ± 0.26 μs 1.03 ± 0.062
launch/3D static workgroup, static ndrange 10.4 ± 0.44 μs 10.2 ± 0.54 μs 1.02 ± 0.069
launch/dynamic workgroup, dynamic ndrange 11.8 ± 0.37 μs 11.6 ± 1.7 μs 1.02 ± 0.15
launch/dynamic workgroup, dynamic ndrange, workgroupsize given 11.9 ± 0.57 μs 11.6 ± 3.1 μs 1.03 ± 0.27
launch/static workgroup, dynamic ndrange 10.5 ± 0.27 μs 12.9 ± 1.2 μs 0.81 ± 0.077
launch/static workgroup, static ndrange 11.5 ± 0.78 μs 14.4 ± 0.44 μs 0.796 ± 0.06
narrow workgroup/masked/W=16 0.725 ± 0.019 ms 0.71 ± 0.018 ms 1.02 ± 0.037
narrow workgroup/masked/W=4 0.697 ± 0.033 ms 0.677 ± 0.029 ms 1.03 ± 0.066
narrow workgroup/unmasked/W=16 0.434 ± 0.016 ms 0.431 ± 0.018 ms 1.01 ± 0.056
narrow workgroup/unmasked/W=4 0.427 ± 0.014 ms 0.424 ± 0.014 ms 1.01 ± 0.048
partition/dynamic workgroup, dynamic ndrange 0.0586 ± 0.0017 μs 0.0596 ± 0.0017 μs 0.983 ± 0.039
partition/static workgroup, dynamic ndrange 0.066 ± 0.012 μs 0.066 ± 0.012 μs 1 ± 0.26
partition/static workgroup, static ndrange 1.55 ± 0.01 ns 1.55 ± 0.01 ns 1 ± 0.0091
saxpy/default/Float16/1024 15 ± 4.3 μs 24.4 ± 1.6 μs 0.617 ± 0.18
saxpy/default/Float16/1048576 1.49 ± 0.035 ms 1.46 ± 0.027 ms 1.02 ± 0.03
saxpy/default/Float16/16384 0.0382 ± 0.016 ms 0.0367 ± 0.0013 ms 1.04 ± 0.44
saxpy/default/Float16/2048 17.6 ± 1.6 μs 15.9 ± 0.73 μs 1.11 ± 0.11
saxpy/default/Float16/256 24.9 ± 15 μs 16.7 ± 1.3 μs 1.49 ± 0.91
saxpy/default/Float16/262144 0.413 ± 0.02 ms 0.41 ± 0.019 ms 1.01 ± 0.068
saxpy/default/Float16/32768 0.0937 ± 0.0098 ms 0.0939 ± 0.014 ms 0.998 ± 0.18
saxpy/default/Float16/4096 22.6 ± 12 μs 20.1 ± 1.2 μs 1.13 ± 0.6
saxpy/default/Float16/512 11.4 ± 5.5 μs 11.3 ± 0.21 μs 1.01 ± 0.49
saxpy/default/Float16/64 11.2 ± 0.48 μs 11.6 ± 0.24 μs 0.959 ± 0.046
saxpy/default/Float16/65536 0.149 ± 0.018 ms 0.148 ± 0.014 ms 1.01 ± 0.16
saxpy/default/Float32/1024 14.8 ± 0.77 μs 13.7 ± 7.1 μs 1.08 ± 0.56
saxpy/default/Float32/1048576 0.835 ± 0.058 ms 0.831 ± 0.048 ms 1 ± 0.091
saxpy/default/Float32/16384 29 ± 15 μs 28 ± 14 μs 1.04 ± 0.74
saxpy/default/Float32/2048 17 ± 1.4 μs 15.2 ± 2 μs 1.12 ± 0.18
saxpy/default/Float32/256 25.3 ± 1.6 μs 15.6 ± 0.76 μs 1.62 ± 0.13
saxpy/default/Float32/262144 0.249 ± 0.022 ms 0.253 ± 0.025 ms 0.985 ± 0.13
saxpy/default/Float32/32768 0.0416 ± 0.0023 ms 0.0404 ± 0.0012 ms 1.03 ± 0.064
saxpy/default/Float32/4096 18.3 ± 0.76 μs 28 ± 0.64 μs 0.655 ± 0.031
saxpy/default/Float32/512 10.7 ± 4.3 μs 9.9 ± 0.41 μs 1.08 ± 0.44
saxpy/default/Float32/64 11.1 ± 0.39 μs 11.2 ± 0.56 μs 0.994 ± 0.061
saxpy/default/Float32/65536 0.0995 ± 0.016 ms 0.0986 ± 0.02 ms 1.01 ± 0.26
saxpy/default/Float64/1024 16 ± 0.63 μs 13.7 ± 2 μs 1.17 ± 0.18
saxpy/default/Float64/1048576 1.04 ± 0.16 ms 1.04 ± 0.2 ms 1 ± 0.25
saxpy/default/Float64/16384 0.044 ± 0.016 ms 0.0415 ± 0.0024 ms 1.06 ± 0.38
saxpy/default/Float64/2048 17 ± 0.76 μs 14.6 ± 8.5 μs 1.16 ± 0.68
saxpy/default/Float64/256 16.3 ± 12 μs 13.9 ± 5.6 μs 1.17 ± 0.96
saxpy/default/Float64/262144 0.272 ± 0.053 ms 0.261 ± 0.041 ms 1.04 ± 0.26
saxpy/default/Float64/32768 0.045 ± 0.0041 ms 0.0457 ± 0.02 ms 0.983 ± 0.45
saxpy/default/Float64/4096 19.1 ± 1.5 μs 18.3 ± 0.83 μs 1.05 ± 0.097
saxpy/default/Float64/512 25.5 ± 0.81 μs 13.2 ± 1.3 μs 1.93 ± 0.2
saxpy/default/Float64/64 23.6 ± 14 μs 15.2 ± 0.36 μs 1.56 ± 0.91
saxpy/default/Float64/65536 0.115 ± 0.021 ms 0.11 ± 0.024 ms 1.04 ± 0.3
saxpy/static workgroup=(1024,)/Float16/1024 15.3 ± 2.3 μs 10.7 ± 0.7 μs 1.44 ± 0.24
saxpy/static workgroup=(1024,)/Float16/1048576 1.47 ± 0.036 ms 1.47 ± 0.021 ms 0.997 ± 0.028
saxpy/static workgroup=(1024,)/Float16/16384 0.0373 ± 0.00084 ms 0.0366 ± 0.015 ms 1.02 ± 0.42
saxpy/static workgroup=(1024,)/Float16/2048 28.6 ± 0.95 μs 16.7 ± 3.6 μs 1.71 ± 0.37
saxpy/static workgroup=(1024,)/Float16/256 11.5 ± 0.38 μs 11.8 ± 4.4 μs 0.971 ± 0.36
saxpy/static workgroup=(1024,)/Float16/262144 0.41 ± 0.023 ms 0.405 ± 0.018 ms 1.01 ± 0.071
saxpy/static workgroup=(1024,)/Float16/32768 0.105 ± 0.015 ms 0.0929 ± 0.014 ms 1.13 ± 0.24
saxpy/static workgroup=(1024,)/Float16/4096 20.6 ± 0.63 μs 19.9 ± 0.75 μs 1.03 ± 0.05
saxpy/static workgroup=(1024,)/Float16/512 25.2 ± 9 μs 11.4 ± 0.26 μs 2.21 ± 0.79
saxpy/static workgroup=(1024,)/Float16/64 11.5 ± 0.69 μs 11.1 ± 0.25 μs 1.03 ± 0.066
saxpy/static workgroup=(1024,)/Float16/65536 0.149 ± 0.016 ms 0.14 ± 0.016 ms 1.06 ± 0.17
saxpy/static workgroup=(1024,)/Float32/1024 14.6 ± 0.7 μs 14.4 ± 13 μs 1.02 ± 0.94
saxpy/static workgroup=(1024,)/Float32/1048576 0.848 ± 0.048 ms 0.851 ± 0.066 ms 0.996 ± 0.096
saxpy/static workgroup=(1024,)/Float32/16384 0.042 ± 0.014 ms 0.0404 ± 0.013 ms 1.04 ± 0.48
saxpy/static workgroup=(1024,)/Float32/2048 17.6 ± 11 μs 25.3 ± 0.72 μs 0.695 ± 0.42
saxpy/static workgroup=(1024,)/Float32/256 25.5 ± 1.3 μs 11.3 ± 0.26 μs 2.26 ± 0.13
saxpy/static workgroup=(1024,)/Float32/262144 0.243 ± 0.019 ms 0.244 ± 0.022 ms 0.998 ± 0.12
saxpy/static workgroup=(1024,)/Float32/32768 0.0618 ± 0.024 ms 0.0403 ± 0.02 ms 1.53 ± 0.96
saxpy/static workgroup=(1024,)/Float32/4096 18.4 ± 0.83 μs 18.4 ± 9.7 μs 1 ± 0.53
saxpy/static workgroup=(1024,)/Float32/512 26.1 ± 0.7 μs 10.5 ± 12 μs 2.5 ± 2.9
saxpy/static workgroup=(1024,)/Float32/64 11.8 ± 0.34 μs 11.7 ± 0.22 μs 1.01 ± 0.035
saxpy/static workgroup=(1024,)/Float32/65536 0.0999 ± 0.019 ms 0.106 ± 0.018 ms 0.939 ± 0.24
saxpy/static workgroup=(1024,)/Float64/1024 16.1 ± 1.3 μs 23.2 ± 8.3 μs 0.692 ± 0.25
saxpy/static workgroup=(1024,)/Float64/1048576 1.05 ± 0.13 ms 1.05 ± 0.21 ms 0.995 ± 0.23
saxpy/static workgroup=(1024,)/Float64/16384 31.5 ± 15 μs 29 ± 2.6 μs 1.09 ± 0.54
saxpy/static workgroup=(1024,)/Float64/2048 17 ± 0.55 μs 16.1 ± 0.5 μs 1.05 ± 0.047
saxpy/static workgroup=(1024,)/Float64/256 14.7 ± 14 μs 11.4 ± 15 μs 1.29 ± 2.1
saxpy/static workgroup=(1024,)/Float64/262144 0.257 ± 0.042 ms 0.257 ± 0.036 ms 1 ± 0.22
saxpy/static workgroup=(1024,)/Float64/32768 0.0452 ± 0.047 ms 0.0601 ± 0.043 ms 0.752 ± 0.95
saxpy/static workgroup=(1024,)/Float64/4096 19.1 ± 1 μs 25.8 ± 8.5 μs 0.739 ± 0.25
saxpy/static workgroup=(1024,)/Float64/512 15.2 ± 2 μs 13.9 ± 0.94 μs 1.09 ± 0.16
saxpy/static workgroup=(1024,)/Float64/64 11.7 ± 6.2 μs 12.3 ± 0.56 μs 0.952 ± 0.51
saxpy/static workgroup=(1024,)/Float64/65536 0.117 ± 0.02 ms 0.108 ± 0.022 ms 1.09 ± 0.29
time_to_load 0.518 ± 0.0029 s 0.514 ± 0.0018 s 1.01 ± 0.0067
main da38f0d... main / da38f0d...
const/@Const/Float32/262144 5 allocs: 0.0938 kB 0 allocs: 0 B
const/@Const/Float32/65536 5 allocs: 0.0938 kB 0 allocs: 0 B
const/@Const/Float64/262144 5 allocs: 0.0938 kB 0 allocs: 0 B
const/@Const/Float64/65536 5 allocs: 0.0938 kB 0 allocs: 0 B
const/unmarked/Float32/262144 5 allocs: 0.0938 kB 0 allocs: 0 B
const/unmarked/Float32/65536 5 allocs: 0.0938 kB 0 allocs: 0 B
const/unmarked/Float64/262144 5 allocs: 0.0938 kB 0 allocs: 0 B
const/unmarked/Float64/65536 5 allocs: 0.0938 kB 0 allocs: 0 B
dgsem/2D/Float32/fluxdiff/element 6 allocs: 0.109 kB 1 allocs: 16 B 7
dgsem/2D/Float32/fluxdiff/node E=8 6 allocs: 0.125 kB 1 allocs: 32 B 4
dgsem/2D/Float32/fluxdiff/node halfsweep E=8 6 allocs: 0.125 kB 1 allocs: 32 B 4
dgsem/2D/Float32/fluxdiff/node halfsweep v-last E=8 6 allocs: 0.125 kB 1 allocs: 32 B 4
dgsem/2D/Float32/weak/element 6 allocs: 0.109 kB 1 allocs: 16 B 7
dgsem/2D/Float32/weak/element private 6 allocs: 0.109 kB 1 allocs: 16 B 7
dgsem/2D/Float32/weak/node localmem E=1 6 allocs: 0.125 kB 1 allocs: 32 B 4
dgsem/2D/Float32/weak/node localmem E=8 6 allocs: 0.125 kB 1 allocs: 32 B 4
dgsem/2D/Float32/weak/node localmem v-last E=1 6 allocs: 0.125 kB 1 allocs: 32 B 4
dgsem/2D/Float32/weak/node localmem v-last E=8 6 allocs: 0.125 kB 1 allocs: 32 B 4
dgsem/2D/Float32/weak/node recompute E=8 6 allocs: 0.125 kB 1 allocs: 32 B 4
dgsem/2D/Float64/fluxdiff/element 6 allocs: 0.109 kB 1 allocs: 16 B 7
dgsem/2D/Float64/fluxdiff/node E=8 6 allocs: 0.125 kB 1 allocs: 32 B 4
dgsem/2D/Float64/fluxdiff/node halfsweep E=8 6 allocs: 0.125 kB 1 allocs: 32 B 4
dgsem/2D/Float64/fluxdiff/node halfsweep v-last E=8 6 allocs: 0.125 kB 1 allocs: 32 B 4
dgsem/2D/Float64/weak/element 6 allocs: 0.109 kB 1 allocs: 16 B 7
dgsem/2D/Float64/weak/element private 6 allocs: 0.109 kB 1 allocs: 16 B 7
dgsem/2D/Float64/weak/node localmem E=1 6 allocs: 0.125 kB 1 allocs: 32 B 4
dgsem/2D/Float64/weak/node localmem E=8 6 allocs: 0.125 kB 1 allocs: 32 B 4
dgsem/2D/Float64/weak/node localmem v-last E=1 6 allocs: 0.125 kB 1 allocs: 32 B 4
dgsem/2D/Float64/weak/node localmem v-last E=8 6 allocs: 0.125 kB 1 allocs: 32 B 4
dgsem/2D/Float64/weak/node recompute E=8 6 allocs: 0.125 kB 1 allocs: 32 B 4
dgsem/3D/Float32/fluxdiff/element 6 allocs: 0.109 kB 1 allocs: 16 B 7
dgsem/3D/Float32/fluxdiff/node E=2 9 allocs: 0.281 kB 4 allocs: 0.188 kB 1.5
dgsem/3D/Float32/fluxdiff/node halfsweep E=1 9 allocs: 0.281 kB 4 allocs: 0.188 kB 1.5
dgsem/3D/Float32/fluxdiff/node halfsweep v-last E=1 9 allocs: 0.281 kB 4 allocs: 0.188 kB 1.5
dgsem/3D/Float32/weak/element 6 allocs: 0.109 kB 1 allocs: 16 B 7
dgsem/3D/Float32/weak/element private 6 allocs: 0.109 kB 1 allocs: 16 B 7
dgsem/3D/Float32/weak/node localmem E=1 9 allocs: 0.281 kB 4 allocs: 0.188 kB 1.5
dgsem/3D/Float32/weak/node localmem E=2 9 allocs: 0.281 kB 4 allocs: 0.188 kB 1.5
dgsem/3D/Float32/weak/node localmem v-last E=1 9 allocs: 0.281 kB 4 allocs: 0.188 kB 1.5
dgsem/3D/Float32/weak/node localmem v-last E=2 9 allocs: 0.281 kB 4 allocs: 0.188 kB 1.5
dgsem/3D/Float32/weak/node recompute E=2 9 allocs: 0.281 kB 4 allocs: 0.188 kB 1.5
dgsem/3D/Float32/weak/slab E=1 6 allocs: 0.125 kB 1 allocs: 32 B 4
dgsem/3D/Float32/weak/slab E=8 6 allocs: 0.125 kB 1 allocs: 32 B 4
dgsem/3D/Float32/weak/slab double-buffered E=1 6 allocs: 0.125 kB 1 allocs: 32 B 4
dgsem/3D/Float32/weak/slab double-buffered E=8 6 allocs: 0.125 kB 1 allocs: 32 B 4
dgsem/3D/Float32/weak/slab double-buffered v-last E=1 6 allocs: 0.125 kB 1 allocs: 32 B 4
dgsem/3D/Float32/weak/slab double-buffered v-last E=8 6 allocs: 0.125 kB 1 allocs: 32 B 4
dgsem/3D/Float32/weak/slab v-last E=1 6 allocs: 0.125 kB 1 allocs: 32 B 4
dgsem/3D/Float32/weak/slab v-last E=8 6 allocs: 0.125 kB 1 allocs: 32 B 4
dgsem/3D/Float64/fluxdiff/element 6 allocs: 0.109 kB 1 allocs: 16 B 7
dgsem/3D/Float64/fluxdiff/node E=2 9 allocs: 0.281 kB 4 allocs: 0.188 kB 1.5
dgsem/3D/Float64/fluxdiff/node halfsweep E=1 9 allocs: 0.281 kB 4 allocs: 0.188 kB 1.5
dgsem/3D/Float64/fluxdiff/node halfsweep v-last E=1 9 allocs: 0.281 kB 4 allocs: 0.188 kB 1.5
dgsem/3D/Float64/weak/element 6 allocs: 0.109 kB 1 allocs: 16 B 7
dgsem/3D/Float64/weak/element private 6 allocs: 0.109 kB 1 allocs: 16 B 7
dgsem/3D/Float64/weak/node localmem E=1 9 allocs: 0.281 kB 4 allocs: 0.188 kB 1.5
dgsem/3D/Float64/weak/node localmem E=2 9 allocs: 0.281 kB 4 allocs: 0.188 kB 1.5
dgsem/3D/Float64/weak/node localmem v-last E=1 9 allocs: 0.281 kB 4 allocs: 0.188 kB 1.5
dgsem/3D/Float64/weak/node localmem v-last E=2 9 allocs: 0.281 kB 4 allocs: 0.188 kB 1.5
dgsem/3D/Float64/weak/node recompute E=2 9 allocs: 0.281 kB 4 allocs: 0.188 kB 1.5
dgsem/3D/Float64/weak/slab E=1 6 allocs: 0.125 kB 1 allocs: 32 B 4
dgsem/3D/Float64/weak/slab E=8 6 allocs: 0.125 kB 1 allocs: 32 B 4
dgsem/3D/Float64/weak/slab double-buffered E=1 6 allocs: 0.125 kB 1 allocs: 32 B 4
dgsem/3D/Float64/weak/slab double-buffered E=8 6 allocs: 0.125 kB 1 allocs: 32 B 4
dgsem/3D/Float64/weak/slab double-buffered v-last E=1 6 allocs: 0.125 kB 1 allocs: 32 B 4
dgsem/3D/Float64/weak/slab double-buffered v-last E=8 6 allocs: 0.125 kB 1 allocs: 32 B 4
dgsem/3D/Float64/weak/slab v-last E=1 6 allocs: 0.125 kB 1 allocs: 32 B 4
dgsem/3D/Float64/weak/slab v-last E=8 6 allocs: 0.125 kB 1 allocs: 32 B 4
launch/3D static workgroup, dynamic ndrange 9 allocs: 0.219 kB 4 allocs: 0.125 kB 1.75
launch/3D static workgroup, static ndrange 9 allocs: 0.219 kB 4 allocs: 0.125 kB 1.75
launch/dynamic workgroup, dynamic ndrange 5 allocs: 0.0938 kB 0 allocs: 0 B
launch/dynamic workgroup, dynamic ndrange, workgroupsize given 5 allocs: 0.0938 kB 0 allocs: 0 B
launch/static workgroup, dynamic ndrange 5 allocs: 0.0938 kB 0 allocs: 0 B
launch/static workgroup, static ndrange 5 allocs: 0.0938 kB 0 allocs: 0 B
narrow workgroup/masked/W=16 5 allocs: 0.0938 kB 0 allocs: 0 B
narrow workgroup/masked/W=4 5 allocs: 0.0938 kB 0 allocs: 0 B
narrow workgroup/unmasked/W=16 5 allocs: 0.0938 kB 0 allocs: 0 B
narrow workgroup/unmasked/W=4 5 allocs: 0.0938 kB 0 allocs: 0 B
partition/dynamic workgroup, dynamic ndrange 2 allocs: 0.0625 kB 2 allocs: 0.0625 kB 1
partition/static workgroup, dynamic ndrange 2 allocs: 32 B 2 allocs: 32 B 1
partition/static workgroup, static ndrange 0 allocs: 0 B 0 allocs: 0 B
saxpy/default/Float16/1024 8 allocs: 0.141 kB 3 allocs: 0.0469 kB 3
saxpy/default/Float16/1048576 8 allocs: 0.141 kB 3 allocs: 0.0469 kB 3
saxpy/default/Float16/16384 8 allocs: 0.141 kB 3 allocs: 0.0469 kB 3
saxpy/default/Float16/2048 8 allocs: 0.141 kB 3 allocs: 0.0469 kB 3
saxpy/default/Float16/256 5 allocs: 0.0938 kB 0 allocs: 0 B
saxpy/default/Float16/262144 8 allocs: 0.141 kB 3 allocs: 0.0469 kB 3
saxpy/default/Float16/32768 8 allocs: 0.141 kB 3 allocs: 0.0469 kB 3
saxpy/default/Float16/4096 8 allocs: 0.141 kB 3 allocs: 0.0469 kB 3
saxpy/default/Float16/512 8 allocs: 0.141 kB 3 allocs: 0.0469 kB 3
saxpy/default/Float16/64 5 allocs: 0.0938 kB 0 allocs: 0 B
saxpy/default/Float16/65536 8 allocs: 0.141 kB 3 allocs: 0.0469 kB 3
saxpy/default/Float32/1024 8 allocs: 0.141 kB 3 allocs: 0.0469 kB 3
saxpy/default/Float32/1048576 8 allocs: 0.141 kB 3 allocs: 0.0469 kB 3
saxpy/default/Float32/16384 8 allocs: 0.141 kB 3 allocs: 0.0469 kB 3
saxpy/default/Float32/2048 8 allocs: 0.141 kB 3 allocs: 0.0469 kB 3
saxpy/default/Float32/256 5 allocs: 0.0938 kB 0 allocs: 0 B
saxpy/default/Float32/262144 8 allocs: 0.141 kB 3 allocs: 0.0469 kB 3
saxpy/default/Float32/32768 8 allocs: 0.141 kB 3 allocs: 0.0469 kB 3
saxpy/default/Float32/4096 8 allocs: 0.141 kB 3 allocs: 0.0469 kB 3
saxpy/default/Float32/512 8 allocs: 0.141 kB 3 allocs: 0.0469 kB 3
saxpy/default/Float32/64 5 allocs: 0.0938 kB 0 allocs: 0 B
saxpy/default/Float32/65536 8 allocs: 0.141 kB 3 allocs: 0.0469 kB 3
saxpy/default/Float64/1024 8 allocs: 0.141 kB 3 allocs: 0.0469 kB 3
saxpy/default/Float64/1048576 8 allocs: 0.141 kB 3 allocs: 0.0469 kB 3
saxpy/default/Float64/16384 8 allocs: 0.141 kB 3 allocs: 0.0469 kB 3
saxpy/default/Float64/2048 8 allocs: 0.141 kB 3 allocs: 0.0469 kB 3
saxpy/default/Float64/256 5 allocs: 0.0938 kB 0 allocs: 0 B
saxpy/default/Float64/262144 8 allocs: 0.141 kB 3 allocs: 0.0469 kB 3
saxpy/default/Float64/32768 8 allocs: 0.141 kB 3 allocs: 0.0469 kB 3
saxpy/default/Float64/4096 8 allocs: 0.141 kB 3 allocs: 0.0469 kB 3
saxpy/default/Float64/512 8 allocs: 0.141 kB 3 allocs: 0.0469 kB 3
saxpy/default/Float64/64 5 allocs: 0.0938 kB 0 allocs: 0 B
saxpy/default/Float64/65536 8 allocs: 0.141 kB 3 allocs: 0.0469 kB 3
saxpy/static workgroup=(1024,)/Float16/1024 8 allocs: 0.141 kB 3 allocs: 0.0469 kB 3
saxpy/static workgroup=(1024,)/Float16/1048576 8 allocs: 0.141 kB 3 allocs: 0.0469 kB 3
saxpy/static workgroup=(1024,)/Float16/16384 8 allocs: 0.141 kB 3 allocs: 0.0469 kB 3
saxpy/static workgroup=(1024,)/Float16/2048 8 allocs: 0.141 kB 3 allocs: 0.0469 kB 3
saxpy/static workgroup=(1024,)/Float16/256 5 allocs: 0.0938 kB 0 allocs: 0 B
saxpy/static workgroup=(1024,)/Float16/262144 8 allocs: 0.141 kB 3 allocs: 0.0469 kB 3
saxpy/static workgroup=(1024,)/Float16/32768 8 allocs: 0.141 kB 3 allocs: 0.0469 kB 3
saxpy/static workgroup=(1024,)/Float16/4096 8 allocs: 0.141 kB 3 allocs: 0.0469 kB 3
saxpy/static workgroup=(1024,)/Float16/512 8 allocs: 0.141 kB 3 allocs: 0.0469 kB 3
saxpy/static workgroup=(1024,)/Float16/64 5 allocs: 0.0938 kB 0 allocs: 0 B
saxpy/static workgroup=(1024,)/Float16/65536 8 allocs: 0.141 kB 3 allocs: 0.0469 kB 3
saxpy/static workgroup=(1024,)/Float32/1024 8 allocs: 0.141 kB 3 allocs: 0.0469 kB 3
saxpy/static workgroup=(1024,)/Float32/1048576 8 allocs: 0.141 kB 3 allocs: 0.0469 kB 3
saxpy/static workgroup=(1024,)/Float32/16384 8 allocs: 0.141 kB 3 allocs: 0.0469 kB 3
saxpy/static workgroup=(1024,)/Float32/2048 8 allocs: 0.141 kB 3 allocs: 0.0469 kB 3
saxpy/static workgroup=(1024,)/Float32/256 5 allocs: 0.0938 kB 0 allocs: 0 B
saxpy/static workgroup=(1024,)/Float32/262144 8 allocs: 0.141 kB 3 allocs: 0.0469 kB 3
saxpy/static workgroup=(1024,)/Float32/32768 8 allocs: 0.141 kB 3 allocs: 0.0469 kB 3
saxpy/static workgroup=(1024,)/Float32/4096 8 allocs: 0.141 kB 3 allocs: 0.0469 kB 3
saxpy/static workgroup=(1024,)/Float32/512 8 allocs: 0.141 kB 3 allocs: 0.0469 kB 3
saxpy/static workgroup=(1024,)/Float32/64 5 allocs: 0.0938 kB 0 allocs: 0 B
saxpy/static workgroup=(1024,)/Float32/65536 8 allocs: 0.141 kB 3 allocs: 0.0469 kB 3
saxpy/static workgroup=(1024,)/Float64/1024 8 allocs: 0.141 kB 3 allocs: 0.0469 kB 3
saxpy/static workgroup=(1024,)/Float64/1048576 8 allocs: 0.141 kB 3 allocs: 0.0469 kB 3
saxpy/static workgroup=(1024,)/Float64/16384 8 allocs: 0.141 kB 3 allocs: 0.0469 kB 3
saxpy/static workgroup=(1024,)/Float64/2048 8 allocs: 0.141 kB 3 allocs: 0.0469 kB 3
saxpy/static workgroup=(1024,)/Float64/256 5 allocs: 0.0938 kB 0 allocs: 0 B
saxpy/static workgroup=(1024,)/Float64/262144 8 allocs: 0.141 kB 3 allocs: 0.0469 kB 3
saxpy/static workgroup=(1024,)/Float64/32768 8 allocs: 0.141 kB 3 allocs: 0.0469 kB 3
saxpy/static workgroup=(1024,)/Float64/4096 8 allocs: 0.141 kB 3 allocs: 0.0469 kB 3
saxpy/static workgroup=(1024,)/Float64/512 8 allocs: 0.141 kB 3 allocs: 0.0469 kB 3
saxpy/static workgroup=(1024,)/Float64/64 5 allocs: 0.0938 kB 0 allocs: 0 B
saxpy/static workgroup=(1024,)/Float64/65536 8 allocs: 0.141 kB 3 allocs: 0.0469 kB 3
time_to_load 0.2 k allocs: 11.8 kB 0.2 k allocs: 11.8 kB 1

Benchmark Plots

A plot of the benchmark results have been uploaded as an artifact to the workflow run for this PR.
Go to "Actions"->"Benchmark a pull request"->[the most recent run]->"Artifacts" (at the bottom).

giordano and others added 3 commits October 17, 2026 11:08
…uple

`compiler_config` is looked up on every launch, and keyed by
`hash(kwargs)`. The generic `hash(::AbstractDict)` iterates over the
`Pairs`, whose values have different types (e.g. `name::Nothing` and
`sub_group_size::Int`), so every element was boxed: 16 bytes per launch.
Hash `values(kwargs)`, a `NamedTuple`, instead, like the other back-ends.

`compiler_config` and `clfunction` of a compiled kernel no longer
allocate, which the new tests check where Julia allows: on 1.10 both
allocate, and on 1.11 GPUCompiler's lookup of the compiled code does.
Bump the version to 0.10.1.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01D6fxP52AyNqfcKSSQXFxfB
…ration

`KI.kernel_function` passed the device's sub-group width to `clfunction`,
as `nothing` on devices without sub-groups. The keyword arguments' type
was thus only known at run time, so the keyword call to `clfunction` was
dynamic: building the `NamedTuple` and boxing the returned kernel
allocated 64 bytes on every launch.

Instead, default the width to the device's in `_compiler_config`, which
only runs when creating a configuration, and don't pass it at all. That
also changes the default of `@opencl` from 32 to that width, which is
the same on devices that support 32, and works on those that don't.

`KI.kernel_function` of a compiled kernel no longer allocates, which a
new test checks.

Co-authored-by: Mosè Giordano <mose@gnu.org>
Every `@checked` OpenCL wrapper runs the API call in a closure passed to
`check`. When `check` isn't inlined, a `Ref` the call writes its result
to is captured by the closure and escapes, so it is heap-allocated even
in callers that inline the wrapper itself. Inline `check`, so that such
a `Ref` can live on the stack.

On its own this doesn't remove an allocation, since the wrappers aren't
inlined where it matters; it allows inlining the wrapper for
`clEnqueueNDRangeKernel`, whose `Ref` for the event is allocated on
every launch.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01D6fxP52AyNqfcKSSQXFxfB
@maleadt
maleadt force-pushed the mg/pocl-rm-launch-allocs branch from 6e895b4 to e06876f Compare October 17, 2026 09:50
`enqueue_kernel` passes a `Ref` for the launch's event to
`clEnqueueNDRangeKernel`, which wasn't inlined, so the `Ref` escaped and
every launch allocated 16 bytes. Inline the wrapper at this call site
(which, with `check` inlined, lets the `Ref` live on the stack).

With this, launching a compiled kernel through KernelAbstractions no
longer allocates (down from 96 bytes on 0.10.0). Waiting for it doesn't
either since GPUToolbox 3.4.1, also when the kernel takes long enough
for the wait to involve a completion callback, so require that. Test
that a launch through `launch_tuple` and `@kernel` launches of a short
and a long kernel don't allocate.

Co-authored-by: Tim Besard <tim.besard@gmail.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01D6fxP52AyNqfcKSSQXFxfB
@maleadt
maleadt force-pushed the mg/pocl-rm-launch-allocs branch from e06876f to da38f0d Compare October 17, 2026 10:26
@maleadt
maleadt merged commit 4279ce1 into main Oct 17, 2026
56 of 61 checks passed
@maleadt
maleadt deleted the mg/pocl-rm-launch-allocs branch October 17, 2026 14:50
@codecov

codecov Bot commented Oct 18, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 82.53%. Comparing base (ba61ff0) to head (da38f0d).
⚠️ Report is 1 commits behind head on main.

Additional details and impacted files
@@           Coverage Diff           @@
##             main     #901   +/-   ##
=======================================
  Coverage   82.53%   82.53%           
=======================================
  Files          28       28           
  Lines        2456     2457    +1     
=======================================
+ Hits         2027     2028    +1     
  Misses        429      429           

☔ 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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

performance Runtime performance. pocl The PoCL-based CPU back-end.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants