Skip to content

Commit f428672

Browse files
committed
Initial implementation of lazy JLLs for LinearAlgebra
This alters CompilerSupportLibraries_jll, OpenBLAS_jll and libblastrampoline_jll to use `LazyLibrary` objects and thereby be loaded only upon first `dlopen()` or `ccall()` to the individual library objects. Note that this is one of the more complicated cases, as `libblastrampoline` must have OpenBLAS_jll added as a dynamic dependency (as it does not actually have it listed in its shared object headers) and also has some on-load callbacks that must be invoked. This must be paired with the appropriate base Julia changes [0]. [0] JuliaLang/julia#57719
1 parent 5122dbf commit f428672

File tree

3 files changed

+21
-13
lines changed

3 files changed

+21
-13
lines changed

src/LinearAlgebra.jl

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -820,25 +820,27 @@ function versioninfo(io::IO=stdout)
820820
return nothing
821821
end
822822

823-
function __init__()
824-
try
825-
verbose = parse(Bool, get(ENV, "LBT_VERBOSE", "false"))
826-
BLAS.lbt_forward(OpenBLAS_jll.libopenblas_path; clear=true, verbose)
827-
BLAS.check()
828-
catch ex
829-
Base.showerror_nostdio(ex, "WARNING: Error during initialization of module LinearAlgebra")
830-
end
823+
function lbt_openblas_onload_callback()
824+
# We don't use `BLAS.lbt_forward()` here because we don't want to take a lock on the config cache.
825+
verbose = parse(Bool, get(ENV, "LBT_VERBOSE", "false"))
826+
BLAS.lbt_forward_ccall(OpenBLAS_jll.libopenblas_path; clear=true, verbose)
827+
BLAS.check()
828+
831829
# register a hook to disable BLAS threading
832830
Base.at_disable_library_threading(() -> BLAS.set_num_threads(1))
833831

834832
# https://github.com/xianyi/OpenBLAS/blob/c43ec53bdd00d9423fc609d7b7ecb35e7bf41b85/README.md#setting-the-number-of-threads-using-environment-variables
835833
if !haskey(ENV, "OPENBLAS_NUM_THREADS") && !haskey(ENV, "GOTO_NUM_THREADS") && !haskey(ENV, "OMP_NUM_THREADS")
836834
@static if Sys.isapple() && Base.BinaryPlatforms.arch(Base.BinaryPlatforms.HostPlatform()) == "aarch64"
837-
BLAS.set_num_threads(max(1, @ccall(jl_effective_threads()::Cint)))
835+
nthreads = max(1, @ccall(jl_effective_threads()::Cint))
838836
else
839-
BLAS.set_num_threads(max(1, @ccall(jl_effective_threads()::Cint) ÷ 2))
837+
nthreads = max(1, @ccall(jl_effective_threads()::Cint) ÷ 2)
840838
end
839+
BLAS.lbt_set_num_threads(nthreads)
841840
end
842841
end
843842

843+
# If users want to lazily load a different BLAS, they'd need to either change this call, or
844+
# clear the datastructures modified by this call and call it again with their own.
845+
libblastrampoline_jll.add_dependency!(OpenBLAS_jll, libopenblas, lbt_openblas_onload_callback)
844846
end # module LinearAlgebra

src/blas.jl

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,9 @@ get_num_threads()::Int = lbt_get_num_threads()
161161
function check()
162162
# TODO: once we have bitfields of the BLAS functions that are actually forwarded,
163163
# ensure that we have a complete set here (warning on an incomplete BLAS implementation)
164-
config = get_config()
164+
# We don't use `get_config()` here because we are invoked in the onload callback and
165+
# we don't want to take any locks.
166+
config = LBTConfig(unsafe_load(ccall((:lbt_get_config, libblastrampoline), Ptr{lbt_config_t}, ())))
165167

166168
# Ensure that one of our loaded libraries satisfies our interface requirement
167169
interface = USE_BLAS64 ? :ilp64 : :lp64

src/lbt.jl

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -228,10 +228,14 @@ function lbt_set_num_threads(nthreads)
228228
return ccall((:lbt_set_num_threads, libblastrampoline), Cvoid, (Int32,), nthreads)
229229
end
230230

231+
function lbt_forward_ccall(path::AbstractString; clear::Bool = false, verbose::Bool = false, suffix_hint::Union{String,Nothing} = nothing)
232+
return ccall((:lbt_forward, libblastrampoline), Int32, (Cstring, Int32, Int32, Cstring),
233+
path, clear ? 1 : 0, verbose ? 1 : 0, something(suffix_hint, C_NULL))
234+
end
235+
231236
function lbt_forward(path::AbstractString; clear::Bool = false, verbose::Bool = false, suffix_hint::Union{String,Nothing} = nothing)
232237
_clear_config_with() do
233-
return ccall((:lbt_forward, libblastrampoline), Int32, (Cstring, Int32, Int32, Cstring),
234-
path, clear ? 1 : 0, verbose ? 1 : 0, something(suffix_hint, C_NULL))
238+
lbt_forward_ccall(path; clear, verbose, suffix_hint)
235239
end
236240
end
237241

0 commit comments

Comments
 (0)