-
-
Notifications
You must be signed in to change notification settings - Fork 5.7k
Add API for non-native compiler caching of external methods #60923
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
…iler caching Non-native compilers (e.g. GPU compilers) that use the AbstractInterpreter framework create CodeInstances with a non-nothing `owner` field to partition their compilation results from the native code cache. Since v1.12.0-DEV.1268, `queue_external_cis` filters CIs with `ci->owner == jl_nothing`, which means non-native CIs for external methods (methods not defined in the package being precompiled, e.g. `Base.identity`) are silently dropped during serialization. CIs for internal methods (defined within the package) survive regardless because the MethodInstance cache is serialized with the module. However, external method CIs must pass through the `new_ext_cis` pathway, where the owner filter rejects them. Simply pushing CIs into `newly_inferred` via `jl_push_newly_inferred` does not help, since that array feeds into `queue_external_cis` which applies the same owner filter. This adds a `Base.precompile(ci::CodeInstance)` method that registers CIs into a separate `newly_inferred_external` array. During `jl_create_system_image`, these CIs are merged directly into `new_ext_cis` after the filtering step, bypassing the owner check entirely. This provides an explicit opt-in API for non-native compilers to persist their external-method CIs into the package image. Co-Authored-By: Claude Opus 4.5 <[email protected]>
|
Seems okay, though I don't see why you needed a separate array for this |
|
Valentin pointed me to #60747, which I hadn't seen and I presume would fix this without any intervention. However, for JuliaC we would probably still need something like this, for now. |
|
Terminology:
It used to be the case that pushing foreign & external CIs into Now, we do a dance of going from julia/Compiler/src/precompile.jl Lines 373 to 396 in 4fe5312
Lines 3400 to 3421 in 4fe5312
Now the crux is that when we go from CI to MI we naturally lose the owner, and then we are asking the question, "is this CI the newest one for the native interpreter", later the only way we can recreate CI is by using the native owner and thus we drop foreign & external CIs. |
vchuravy
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am thinking we can avoid a precompile(ci) and a new global array.
In
julia/Compiler/src/precompile.jl
Lines 376 to 379 in 4fe5312
| for i in 1:length(new_ext_cis::Vector{Any}) | |
| ci = new_ext_cis[i]::CodeInstance | |
| enqueue_specialization!(all, specialization_worklist, get_ci_mi(ci)) | |
| end |
jl_create_system_image
|
#60747 now takes part of this approach, but removes the requirement of having a new API |
Non-native compilers that use the AbstractInterpreter framework create CodeInstances with a non-nothing
ownerfield to partition their compilation results from the native code cache. Since #54894,queue_external_cisfilters CIs withci->owner == jl_nothing, which sometimes means non-native CIs for external methods are silently dropped during serialization. @vchuravy This may explain the breakage seen in GPUCompiler.jl/CompilerCaching.jl for the test you added? I don't fully understand the whole mechanism for discovering/caching CIs though.This PR adds an explicit
Base.precompile(ci::CodeInstance)API to registers CIs into a separatenewly_inferred_externalarray. Duringjl_create_system_image, these CIs are merged directly intonew_ext_cisafter the filtering step, bypassing the owner check entirely.IIUC This would also be useful for compiling non-native workloads with JuliaC.jl, as a simpler alternative to
invoke_in_cacheorinvoke_with_absint.Corresponding CompilerCaching.jl PR: maleadt/CompilerCaching.jl#3
cc @gbaraldi This resembles what we discussed yesterday.
cc @vchuravy You've worked on this before
cc @vtjnash Having authored #54894