Skip to content

Precompile the Metal operations that depend on the extension's tunings - #200

Open
maleadt wants to merge 1 commit into
mainfrom
tb/metal-workload
Open

maleadt wants to merge 1 commit into
mainfrom
tb/metal-workload

Conversation

@maleadt

@maleadt maleadt commented Oct 28, 2026

Copy link
Copy Markdown
Member

Metal.jl's package image can't hold AcceleratedKernels' operations as they run on Metal: this extension isn't loaded while Metal precompiles, so the kernels its workload compiles use the default tunings rather than the ones set here, and the first sum, cumsum or any of a session compiles its host code and kernels again. (The inference barriers of #189 prevent invalidations, but can't make those kernels match.)

This adds a @compile_workload to the extension that covers whole-array reductions (both passes), reductions of a matrix along either dimension, cumsum, any and all of Float32 arrays, and the sum of an Int array, at sizes that select the same kernels as a vector of 10^6 elements and a 1000×1000 matrix. Like Metal's own workload it runs on Julia 1.11 and later, and only when Metal's workload launches kernels too, which it reports with Metal.can_precompile_launches (JuliaGPU/Metal.jl#1124); with older versions of Metal, which can't tell and implement some of these operations differently, it is skipped.

M1, Julia 1.13, first … before after
sum 448 ms 52 ms
sum(; dims=1) 293 ms 106 ms
sum(; dims=2) 199 ms 30 ms
cumsum 708 ms 78 ms
any 728 ms 97 ms
all 339 ms 30 ms
Int sum 308 ms 24 ms

(Together with Metal.jl#1124 the first sum takes 15 ms and cumsum 24 ms.) Loading Metal takes no measurable extra time; the extension's image grows from 0.08 to 6.6 MB and its precompilation from 2.3 to 5.5 s. Operations it doesn't cover, like maximum, count or Int cumsum, aren't affected.

Metal's package image can't hold AcceleratedKernels' operations as
they run on Metal: this extension isn't loaded while Metal
precompiles, so the kernels its workload compiles use the default
tunings, and the first `sum`, `cumsum` or `any` of a session compiles
its host code and kernels again. A `@compile_workload` in the
extension caches them with the tunings that apply.

It covers whole-array reductions (both passes), reductions of a
matrix along either dimension, `cumsum`, `any` and `all` of Float32
arrays, and the sum of an Int array. On an M1 with Julia 1.13, the
first call on 10^6 elements or a 1000x1000 matrix takes 50 ms instead
of 450 for `sum`, 80 instead of 710 for `cumsum`, 100 instead of 730
for `any`, and 110 and 30 instead of 290 and 200 for `sum` along
`dims=1` and `dims=2`. The extension's image grows by 6.5 MB, and
loading Metal takes no measurable extra time.

As in Metal's own workload, it runs on Julia 1.11 and later only, and
only when Metal's workload launches kernels too, which it reports with
`Metal.can_precompile_launches` (JuliaGPU/Metal.jl#1124). With older
versions of Metal, which can't tell and implement some of these
operations differently, the workload is skipped.

This branch has not been deployed

No deployments
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