|
1 | 1 | module AppleAccelerate
|
2 | 2 |
|
3 |
| -using Libdl |
| 3 | +using LinearAlgebra |
| 4 | +using Libdl, LAPACK_jll, LAPACK32_jll |
4 | 5 |
|
5 |
| -if Sys.isapple() |
| 6 | +# For now, only use BLAS from Accelerate (that is to say, vecLib) |
| 7 | +global const libacc = "/System/Library/Frameworks/Accelerate.framework/Accelerate" |
| 8 | +global const libacc_info_plist = "/System/Library/Frameworks/Accelerate.framework/Versions/Current/Resources/Info.plist" |
| 9 | + |
| 10 | +function forward_accelerate(interface::Symbol; |
| 11 | + new_lapack::Bool = interface == :ilp64, |
| 12 | + clear::Bool = false, |
| 13 | + verbose::Bool = false) |
| 14 | + kwargs = Dict{Symbol,String}() |
| 15 | + if new_lapack |
| 16 | + if interface == :ilp64 |
| 17 | + kwargs[:suffix_hint] = "\x1a\$NEWLAPACK\$ILP64" |
| 18 | + else |
| 19 | + kwargs[:suffix_hint] = "\x1a\$NEWLAPACK" |
| 20 | + end |
| 21 | + else |
| 22 | + if interface == :ilp64 |
| 23 | + throw(ArgumentError("ILP64 accelerate requires new_lapack")) |
| 24 | + end |
| 25 | + end |
| 26 | + BLAS.lbt_forward(libacc; clear, verbose, kwargs...) |
| 27 | +end |
| 28 | + |
| 29 | +""" |
| 30 | + load_accelerate(;clear = true, verbose = false) |
| 31 | +
|
| 32 | +Load Accelerate, replacing the current LBT forwarding tables if `clear` is `true`. |
| 33 | +Attempts to load the ILP64 symbols if `load_ilp64` is `true`, and errors out if unable. |
| 34 | +""" |
| 35 | +function load_accelerate(;clear::Bool = true, verbose::Bool = false, load_ilp64::Bool = true, use_external_lapack::Bool = true) |
| 36 | + # Silently exit on non-Accelerate-capable platforms |
| 37 | + @static if !Sys.isapple() |
| 38 | + return |
| 39 | + end |
| 40 | + libacc_hdl = dlopen_e(libacc) |
| 41 | + if libacc_hdl == C_NULL |
| 42 | + return |
| 43 | + end |
| 44 | + |
| 45 | + # Check to see if we can load ILP64 symbols |
| 46 | + if load_ilp64 && dlsym_e(libacc_hdl, "dgemm\$NEWLAPACK\$ILP64") == C_NULL |
| 47 | + error("Unable to load ILP64 interface from '$(libacc)'; You are running macOS version $(get_macos_version()), you need v13.3+") |
| 48 | + end |
| 49 | + |
| 50 | + # First, load :lp64 symbols, optionally clearing the current LBT forwarding tables |
| 51 | + forward_accelerate(:lp64; new_lapack=true, clear, verbose) |
| 52 | + if load_ilp64 |
| 53 | + forward_accelerate(:ilp64; new_lapack=true, verbose) |
| 54 | + end |
6 | 55 |
|
7 |
| - try |
8 |
| - global const libacc = "/System/Library/Frameworks/Accelerate.framework/Accelerate" |
9 |
| - let accel_lib = dlopen(libacc) |
10 |
| - dlclose(accel_lib) |
| 56 | + # Next, load an external LAPACK, if requested |
| 57 | + if use_external_lapack |
| 58 | + if load_ilp64 |
| 59 | + BLAS.lbt_forward(LAPACK_jll.liblapack_path; suffix_hint="64_", verbose) |
11 | 60 | end
|
12 |
| - catch |
13 |
| - error("Accelerate framework not found.") |
| 61 | + BLAS.lbt_forward(LAPACK32_jll.liblapack32_path; verbose) |
| 62 | + end |
| 63 | +end |
| 64 | + |
| 65 | +function get_macos_version() |
| 66 | + @static if !Sys.isapple() |
| 67 | + return nothing |
14 | 68 | end
|
15 | 69 |
|
| 70 | + plist_lines = split(String(read("/System/Library/CoreServices/SystemVersion.plist")), "\n") |
| 71 | + vers_idx = findfirst(l -> occursin("ProductVersion", l), plist_lines) |
| 72 | + if vers_idx === nothing |
| 73 | + return nothing |
| 74 | + end |
| 75 | + |
| 76 | + m = match(r">([\d\.]+)<", plist_lines[vers_idx+1]) |
| 77 | + if m === nothing |
| 78 | + return nothing |
| 79 | + end |
16 | 80 |
|
| 81 | + return VersionNumber(only(m.captures)) |
| 82 | +end |
| 83 | + |
| 84 | +function __init__() |
| 85 | + # Default to loading the ILP64 interface on macOS 13.3+ |
| 86 | + ver = get_macos_version() |
| 87 | + ver == nothing && return |
| 88 | + load_ilp64 = ver >= v"13.3" |
| 89 | + # dsptrf has a bug in the initial release of the $NEWLAPACK symbols, so if we're |
| 90 | + # on a version older than macOS 13.4, use an external LAPACK: |
| 91 | + load_accelerate(; load_ilp64, use_external_lapack = ver < v"13.4") |
| 92 | +end |
| 93 | + |
| 94 | +if Sys.isapple() |
17 | 95 | include("Array.jl")
|
18 | 96 | include("DSP.jl")
|
19 | 97 | include("Util.jl")
|
20 |
| - |
21 | 98 | end
|
22 | 99 |
|
23 | 100 | end # module
|
0 commit comments