Skip to content

Commit f6b05c4

Browse files
committed
Document backend interfaces and caching
1 parent e2fb67b commit f6b05c4

26 files changed

Lines changed: 652 additions & 68 deletions

.github/workflows/Test.yml

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,23 @@ concurrency:
1212
cancel-in-progress: true
1313

1414
jobs:
15+
documentation:
16+
name: Documentation
17+
runs-on: ubuntu-latest
18+
steps:
19+
- uses: actions/checkout@v7
20+
- uses: julia-actions/setup-julia@v3
21+
with:
22+
version: '1'
23+
- uses: julia-actions/cache@v3
24+
- name: Install dependencies
25+
run: julia --project=docs -e 'using Pkg; Pkg.develop(PackageSpec(path=pwd())); Pkg.instantiate()'
26+
- name: Build and deploy
27+
env:
28+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
29+
DOCUMENTER_KEY: ${{ secrets.DOCUMENTER_KEY }}
30+
run: julia --project=docs docs/make.jl
31+
1532
release_test:
1633
name: Julia ${{ matrix.version }} ${{ matrix.llvm_args }} - ${{ matrix.os }}
1734
runs-on: ${{ matrix.os }}

README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@
1818
[codecov-img]: https://codecov.io/gh/JuliaGPU/GPUCompiler.jl/branch/main/graph/badge.svg
1919
[codecov-url]: https://codecov.io/gh/JuliaGPU/GPUCompiler.jl
2020

21+
Backend interface and caching documentation is available at
22+
[JuliaGPU.github.io/GPUCompiler.jl](https://juliagpu.github.io/GPUCompiler.jl/dev/).
23+
2124
This package offers reusable compiler infrastructure and tooling for
2225
implementing GPU compilers in Julia. **It is not intended for end users!**
2326
Instead, you should use one of the packages that builds on GPUCompiler.jl, such

docs/Project.toml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
[deps]
2+
Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4"
3+
GPUCompiler = "61eb1bfa-7361-4325-ad38-22787b887f55"
4+
5+
[compat]
6+
Documenter = "1"

docs/make.jl

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
using Documenter, GPUCompiler
2+
3+
function main()
4+
ci = get(ENV, "CI", "") == "true"
5+
6+
makedocs(
7+
sitename = "GPUCompiler.jl",
8+
authors = "Tim Besard",
9+
modules = [GPUCompiler],
10+
format = Documenter.HTML(prettyurls=ci),
11+
pages = [
12+
"Home" => "index.md",
13+
"Interface" => [
14+
"interface/types.md",
15+
"interface/target.md",
16+
"interface/compiler-jobs.md",
17+
"interface/compilation-hooks.md",
18+
"interface/caching.md",
19+
"interface/host-references.md",
20+
],
21+
"Utilities" => [
22+
"utilities/compilation.md",
23+
"utilities/launch.md",
24+
"utilities/reflection.md",
25+
],
26+
],
27+
doctest = true,
28+
doctestfilters = [
29+
r"0x[0-9a-f]+",
30+
r"@julia_\\w+_\\d+",
31+
r"(?s)\nStacktrace:.*",
32+
],
33+
checkdocs = :public,
34+
)
35+
36+
if ci
37+
deploydocs(repo="github.com/JuliaGPU/GPUCompiler.jl.git")
38+
end
39+
end
40+
41+
isinteractive() || main()

docs/src/index.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# GPUCompiler.jl
2+
3+
GPUCompiler.jl is infrastructure for packages that implement Julia GPU backends. It is not an
4+
end-user GPU package: use a backend such as [CUDA.jl](https://github.com/JuliaGPU/CUDA.jl),
5+
[AMDGPU.jl](https://github.com/JuliaGPU/AMDGPU.jl), or
6+
[Metal.jl](https://github.com/JuliaGPU/Metal.jl) to compile and launch kernels.
7+
8+
The Interface section documents the contract between GPUCompiler and backend packages: the
9+
types they construct, the methods they implement, and the metadata they carry through the
10+
compiler. Utilities are reusable building blocks for compilation, launch macros, and reflection;
11+
backends call or re-expose them but do not extend them.

docs/src/interface/caching.md

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
# Caching
2+
3+
```@meta
4+
DocTestSetup = quote
5+
using GPUCompiler
6+
end
7+
```
8+
9+
GPUCompiler separates Julia inference caching from backend artifact caching. `cache_owner`
10+
partitions inference by the target, parameters, and inlining policy. Backends should override it
11+
only with an immutable value whose identity is stable after package-image deserialization.
12+
13+
Use `cached_results` with a zero-argument mutable results struct to retain backend artifacts.
14+
Store portable fields such as object bytes and entry names there. Device modules, functions, and
15+
other runtime handles are session-local: leave them empty in a package image and construct them
16+
after loading the portable artifact. CUDA, OpenCL, oneAPI, and Metal all use this shape.
17+
18+
On Julia 1.11 and newer, results are attached to Julia's code cache and follow its invalidation.
19+
On Julia 1.10 they are process-local. `cached_compilation` is the older, session-local API still
20+
used by AMDGPU and should not be used by new backends.
21+
22+
```@docs
23+
GPUCompiler.GPUCompilerCacheToken
24+
GPUCompiler.cache_owner
25+
GPUCompiler.cached_results
26+
GPUCompiler.cached_compilation
27+
```
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
# Compilation hooks
2+
3+
```@meta
4+
DocTestSetup = quote
5+
using GPUCompiler
6+
end
7+
```
8+
9+
GPUCompiler calls these hooks in pipeline order. A backend can prepare inference state, link
10+
vendor libraries, transform the initial or linked module, customize later optimization stages,
11+
and add target validation. Hooks that receive an entry function must return it because a
12+
transformation may replace the function.
13+
14+
Current backends use only the stages they need: CUDA and AMDGPU link vendor libraries; CUDA,
15+
OpenCL, oneAPI, Metal, and AMDGPU finalize the initial module; OpenCL additionally transforms the
16+
linked module; and oneAPI and Metal perform final IR rewrites.
17+
18+
```@docs
19+
GPUCompiler.prepare_job!
20+
GPUCompiler.link_libraries!
21+
GPUCompiler.finish_module!
22+
GPUCompiler.finish_linked_module!
23+
GPUCompiler.optimize_module!
24+
GPUCompiler.finish_runtime_intrinsics!
25+
GPUCompiler.finish_ir!
26+
GPUCompiler.validate_ir
27+
```
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
# Compiler jobs
2+
3+
```@meta
4+
DocTestSetup = quote
5+
using GPUCompiler
6+
end
7+
```
8+
9+
Job hooks describe the backend environment seen by Julia inference and LLVM lowering. CUDA,
10+
AMDGPU, and Metal provide a method table directly; OpenCL and oneAPI compose method-table views.
11+
All five supply a runtime module and classify target intrinsics. Backends with device-side state
12+
also provide a kernel-state type.
13+
14+
Inference hooks must only depend on the job world and the target, parameters, and inlining policy
15+
covered by `cache_owner`. Other `CompilerConfig` fields affect code generation but do not create
16+
separate inference owners.
17+
18+
```@docs
19+
GPUCompiler.uses_julia_runtime
20+
GPUCompiler.optimization_options
21+
GPUCompiler.can_vectorize
22+
GPUCompiler.dump_native
23+
GPUCompiler.runtime_module
24+
GPUCompiler.isintrinsic
25+
GPUCompiler.get_interpreter
26+
GPUCompiler.can_throw
27+
GPUCompiler.can_safepoint
28+
GPUCompiler.kernel_state_type
29+
GPUCompiler.pass_by_value
30+
GPUCompiler.pass_by_ref
31+
GPUCompiler.valid_function_pointer
32+
GPUCompiler.method_table
33+
GPUCompiler.method_table_view
34+
GPUCompiler.inference_params
35+
GPUCompiler.optimization_params
36+
GPUCompiler.llvm_debug_info
37+
```
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
# Host references
2+
3+
```@meta
4+
DocTestSetup = quote
5+
using GPUCompiler
6+
end
7+
```
8+
9+
Generated IR can refer to either a Julia value or a libjulia C data global. GPUCompiler
10+
normalizes both forms into `HostReferences`: a Julia value becomes a `JuliaValueRef`, and a C
11+
global becomes a `CGlobalRef`. This metadata follows the LLVM module through deferred linking,
12+
optimization, and final code generation.
13+
14+
The default `lower_host_references!` resolves every live reference in the current Julia session
15+
before machine-code generation. A backend with a loader can instead leave writable word-sized
16+
symbols in its object, load the object, resolve and patch every symbol, then expose the callable
17+
function. A Julia value whose address is written into device storage must stay rooted for as
18+
long as that storage can be reached.
19+
20+
CUDA.jl implements that loader path as follows:
21+
22+
```julia
23+
function GPUCompiler.lower_host_references!(job::AnyCUDAJob, mod::LLVM.Module,
24+
refs::GPUCompiler.HostReferences)
25+
GPUCompiler.emit_host_reference_slots!(mod, refs)
26+
end
27+
28+
roots = Any[]
29+
for (name, ref) in refs.slots
30+
slot = CuGlobal{UInt}(mod, name)
31+
slot[] = GPUCompiler.resolve_host_reference(ref)
32+
ref isa GPUCompiler.JuliaValueRef && push!(roots, ref.value)
33+
end
34+
```
35+
36+
See [CUDA.jl's implementation](https://github.com/JuliaGPU/CUDA.jl) for the complete loader
37+
path. `embedded_pointer` is independent of unresolved loader slots: it remains a conservative
38+
signal that a session pointer was embedded and the cached artifact must be evicted before
39+
package-image serialization.
40+
41+
```@docs
42+
GPUCompiler.JuliaValueRef
43+
GPUCompiler.CGlobalRef
44+
GPUCompiler.HostReference
45+
GPUCompiler.HostReferences
46+
GPUCompiler.lower_host_references!
47+
GPUCompiler.emit_host_reference_slots!
48+
GPUCompiler.resolve_host_reference
49+
```

docs/src/interface/target.md

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
# Target
2+
3+
```@meta
4+
DocTestSetup = quote
5+
using GPUCompiler
6+
end
7+
```
8+
9+
Concrete targets live in GPUCompiler and describe the LLVM backend. Most downstream packages
10+
select one of the supplied PTX, GCN, SPIR-V, Metal, BPF, or native targets; a package that adds a
11+
target implements the properties below.
12+
13+
Nested compilation can translate both the target and backend parameters relative to the parent
14+
job. The default methods preserve both values.
15+
16+
## Supplied targets
17+
18+
```@docs
19+
GPUCompiler.PTXCompilerTarget
20+
GPUCompiler.GCNCompilerTarget
21+
GPUCompiler.SPIRVCompilerTarget
22+
GPUCompiler.MetalCompilerTarget
23+
GPUCompiler.BPFCompilerTarget
24+
GPUCompiler.NativeCompilerTarget
25+
```
26+
27+
## Target properties
28+
29+
```@docs
30+
GPUCompiler.source_code
31+
GPUCompiler.llvm_triple
32+
GPUCompiler.llvm_machine
33+
GPUCompiler.llvm_datalayout
34+
GPUCompiler.llvm_targetinfo
35+
GPUCompiler.julia_datalayout
36+
GPUCompiler.have_fma
37+
GPUCompiler.dwarf_version
38+
GPUCompiler.nest_target
39+
GPUCompiler.nest_params
40+
```

0 commit comments

Comments
 (0)