Skip to content

Commit a17a5b3

Browse files
maleadtclaude
andauthored
Make the runtime library disk cache best-effort. (#869)
The cache directory is shared across processes and can be deleted at any point (e.g. by `reset_runtime()`), racing concurrent compilation. Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
1 parent 318b07e commit a17a5b3

2 files changed

Lines changed: 46 additions & 6 deletions

File tree

src/rtlib.jl

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -139,23 +139,35 @@ end
139139
name = "runtime_$(slug).bc"
140140
path = joinpath(compile_cache, name)
141141

142-
if !ispath(path)
143-
@debug "Building the GPU runtime library at $path"
144-
mkpath(compile_cache)
145-
lib = build_runtime(job)
142+
# the cache is shared across processes and may disappear at any point
143+
# (e.g. `reset_runtime()` in another process), so treat it as best-effort
144+
if ispath(path)
145+
try
146+
return parse(LLVM.Module, MemoryBufferFile(path); lazy=true)
147+
catch err
148+
@debug "Failed to load cached GPU runtime library; rebuilding" exception=(err, catch_backtrace())
149+
end
150+
end
146151

152+
@debug "Building the GPU runtime library at $path"
153+
lib = build_runtime(job)
154+
155+
try
147156
# atomic write to disk
148-
temp_path, io = mktemp(dirname(path); cleanup=false)
157+
mkpath(compile_cache)
158+
temp_path, io = mktemp(compile_cache; cleanup=false)
149159
write(io, lib)
150160
close(io)
151161
@static if VERSION >= v"1.12.0-DEV.1023"
152162
mv(temp_path, path; force=true)
153163
else
154164
Base.rename(temp_path, path, force=true)
155165
end
166+
catch err
167+
@warn "Failed to cache GPU runtime library" exception=(err, catch_backtrace()) maxlog=1
156168
end
157169

158-
return parse(LLVM.Module, MemoryBufferFile(path); lazy=true)
170+
return lib
159171
end
160172

161173
# remove the existing cache

test/ptx.jl

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,34 @@ end
3232
@test occursin("[1 x i64] %state", ir)
3333
end
3434

35+
@testset "runtime cache disappearing" begin
36+
# the cache may be deleted or unusable at any point; compilation should keep working
37+
mod = @eval module $(gensym())
38+
kernel() = return
39+
end
40+
old_cache = GPUCompiler.compile_cache
41+
try
42+
GPUCompiler.compile_cache = mktempdir()
43+
PTX.code_llvm(devnull, mod.kernel, Tuple{}; kernel=true)
44+
@test !isempty(readdir(GPUCompiler.compile_cache))
45+
46+
# remove the cache directory altogether
47+
GPUCompiler.reset_runtime()
48+
PTX.code_llvm(devnull, mod.kernel, Tuple{}; kernel=true)
49+
@test !isempty(readdir(GPUCompiler.compile_cache))
50+
51+
# make the cache unwritable; compilation should proceed with only a warning
52+
GPUCompiler.reset_runtime()
53+
write(GPUCompiler.compile_cache, "not a directory")
54+
@test_logs (:warn, r"Failed to cache GPU runtime library") match_mode=:any begin
55+
PTX.code_llvm(devnull, mod.kernel, Tuple{}; kernel=true)
56+
end
57+
rm(GPUCompiler.compile_cache)
58+
finally
59+
GPUCompiler.compile_cache = old_cache
60+
end
61+
end
62+
3563
@testset "kernel functions" begin
3664
@testset "kernel argument attributes" begin
3765
mod = @eval module $(gensym())

0 commit comments

Comments
 (0)