Skip to content

Commit a6edf87

Browse files
Add availability checks for MKL and OpenBLAS similar to AppleAccelerate (#751)
* Add availability checks for MKL and OpenBLAS similar to AppleAccelerate This commit adds runtime availability checks for MKL and OpenBLAS libraries to ensure proper error handling when the libraries are not available. The implementation follows the same pattern as AppleAccelerateLU: - Added __mkl_isavailable() function to check MKL library availability - Added __openblas_isavailable() function to check OpenBLAS library availability - Added error checks in all getrf!, getrs!, and solve! functions - Uses Libdl to check for library symbols at runtime This ensures that calls properly compile out when the binaries are missing and provides clear error messages when the libraries are not available. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]> * Simplify availability checks - remove try/catch and symbol checking Per review feedback, simplified the availability checks: - Removed try/catch blocks as they're unnecessary - Removed Libdl symbol checking - if the binary exists via is_available(), it's fine - Just check if the JLL module is defined and is_available() returns true This makes the code cleaner and follows the principle that if the binary exists, we can trust it has the required symbols. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]> * Use @static if for compile-time availability checks Changed the availability check functions to use @static if for compile-time determination, matching the pattern used in AppleAccelerate: - Uses @static if to check @isdefined at compile time - Returns is_available() result statically when JLL is defined - Returns false statically when JLL is not defined This makes the checks more efficient as they're resolved at compile time rather than runtime. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]> --------- Co-authored-by: Claude <[email protected]>
1 parent 2ff3977 commit a6edf87

File tree

2 files changed

+50
-1
lines changed

2 files changed

+50
-1
lines changed

src/mkl.jl

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,19 @@ to avoid allocations and does not require libblastrampoline.
88
"""
99
struct MKLLUFactorization <: AbstractFactorization end
1010

11+
# Check if MKL is available
12+
@static if !@isdefined(MKL_jll)
13+
__mkl_isavailable() = false
14+
else
15+
__mkl_isavailable() = MKL_jll.is_available()
16+
end
1117

1218
function getrf!(A::AbstractMatrix{<:ComplexF64};
1319
ipiv = similar(A, BlasInt, min(size(A, 1), size(A, 2))),
1420
info = Ref{BlasInt}(),
1521
check = false)
22+
__mkl_isavailable() ||
23+
error("Error, MKL binary is missing but solve is being called. Report this issue")
1624
require_one_based_indexing(A)
1725
check && chkfinite(A)
1826
chkstride1(A)
@@ -33,6 +41,8 @@ function getrf!(A::AbstractMatrix{<:ComplexF32};
3341
ipiv = similar(A, BlasInt, min(size(A, 1), size(A, 2))),
3442
info = Ref{BlasInt}(),
3543
check = false)
44+
__mkl_isavailable() ||
45+
error("Error, MKL binary is missing but solve is being called. Report this issue")
3646
require_one_based_indexing(A)
3747
check && chkfinite(A)
3848
chkstride1(A)
@@ -53,6 +63,8 @@ function getrf!(A::AbstractMatrix{<:Float64};
5363
ipiv = similar(A, BlasInt, min(size(A, 1), size(A, 2))),
5464
info = Ref{BlasInt}(),
5565
check = false)
66+
__mkl_isavailable() ||
67+
error("Error, MKL binary is missing but solve is being called. Report this issue")
5668
require_one_based_indexing(A)
5769
check && chkfinite(A)
5870
chkstride1(A)
@@ -73,6 +85,8 @@ function getrf!(A::AbstractMatrix{<:Float32};
7385
ipiv = similar(A, BlasInt, min(size(A, 1), size(A, 2))),
7486
info = Ref{BlasInt}(),
7587
check = false)
88+
__mkl_isavailable() ||
89+
error("Error, MKL binary is missing but solve is being called. Report this issue")
7690
require_one_based_indexing(A)
7791
check && chkfinite(A)
7892
chkstride1(A)
@@ -94,6 +108,8 @@ function getrs!(trans::AbstractChar,
94108
ipiv::AbstractVector{BlasInt},
95109
B::AbstractVecOrMat{<:ComplexF64};
96110
info = Ref{BlasInt}())
111+
__mkl_isavailable() ||
112+
error("Error, MKL binary is missing but solve is being called. Report this issue")
97113
require_one_based_indexing(A, ipiv, B)
98114
LinearAlgebra.LAPACK.chktrans(trans)
99115
chkstride1(A, B, ipiv)
@@ -119,6 +135,8 @@ function getrs!(trans::AbstractChar,
119135
ipiv::AbstractVector{BlasInt},
120136
B::AbstractVecOrMat{<:ComplexF32};
121137
info = Ref{BlasInt}())
138+
__mkl_isavailable() ||
139+
error("Error, MKL binary is missing but solve is being called. Report this issue")
122140
require_one_based_indexing(A, ipiv, B)
123141
LinearAlgebra.LAPACK.chktrans(trans)
124142
chkstride1(A, B, ipiv)
@@ -144,6 +162,8 @@ function getrs!(trans::AbstractChar,
144162
ipiv::AbstractVector{BlasInt},
145163
B::AbstractVecOrMat{<:Float64};
146164
info = Ref{BlasInt}())
165+
__mkl_isavailable() ||
166+
error("Error, MKL binary is missing but solve is being called. Report this issue")
147167
require_one_based_indexing(A, ipiv, B)
148168
LinearAlgebra.LAPACK.chktrans(trans)
149169
chkstride1(A, B, ipiv)
@@ -169,6 +189,8 @@ function getrs!(trans::AbstractChar,
169189
ipiv::AbstractVector{BlasInt},
170190
B::AbstractVecOrMat{<:Float32};
171191
info = Ref{BlasInt}())
192+
__mkl_isavailable() ||
193+
error("Error, MKL binary is missing but solve is being called. Report this issue")
172194
require_one_based_indexing(A, ipiv, B)
173195
LinearAlgebra.LAPACK.chktrans(trans)
174196
chkstride1(A, B, ipiv)
@@ -213,6 +235,8 @@ end
213235

214236
function SciMLBase.solve!(cache::LinearCache, alg::MKLLUFactorization;
215237
kwargs...)
238+
__mkl_isavailable() ||
239+
error("Error, MKL binary is missing but solve is being called. Report this issue")
216240
A = cache.A
217241
A = convert(AbstractMatrix, A)
218242
if cache.isfresh
@@ -266,6 +290,8 @@ end
266290

267291
function SciMLBase.solve!(cache::LinearCache, alg::MKL32MixedLUFactorization;
268292
kwargs...)
293+
__mkl_isavailable() ||
294+
error("Error, MKL binary is missing but solve is being called. Report this issue")
269295
A = cache.A
270296
A = convert(AbstractMatrix, A)
271297

src/openblas.jl

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,12 +33,19 @@ sol = solve(prob, OpenBLASLUFactorization())
3333
"""
3434
struct OpenBLASLUFactorization <: AbstractFactorization end
3535

36-
# OpenBLAS methods - OpenBLAS_jll is always available as a standard library
36+
# Check if OpenBLAS is available
37+
@static if !@isdefined(OpenBLAS_jll)
38+
__openblas_isavailable() = false
39+
else
40+
__openblas_isavailable() = OpenBLAS_jll.is_available()
41+
end
3742

3843
function openblas_getrf!(A::AbstractMatrix{<:ComplexF64};
3944
ipiv = similar(A, BlasInt, min(size(A, 1), size(A, 2))),
4045
info = Ref{BlasInt}(),
4146
check = false)
47+
__openblas_isavailable() ||
48+
error("Error, OpenBLAS binary is missing but solve is being called. Report this issue")
4249
require_one_based_indexing(A)
4350
check && chkfinite(A)
4451
chkstride1(A)
@@ -59,6 +66,8 @@ function openblas_getrf!(A::AbstractMatrix{<:ComplexF32};
5966
ipiv = similar(A, BlasInt, min(size(A, 1), size(A, 2))),
6067
info = Ref{BlasInt}(),
6168
check = false)
69+
__openblas_isavailable() ||
70+
error("Error, OpenBLAS binary is missing but solve is being called. Report this issue")
6271
require_one_based_indexing(A)
6372
check && chkfinite(A)
6473
chkstride1(A)
@@ -79,6 +88,8 @@ function openblas_getrf!(A::AbstractMatrix{<:Float64};
7988
ipiv = similar(A, BlasInt, min(size(A, 1), size(A, 2))),
8089
info = Ref{BlasInt}(),
8190
check = false)
91+
__openblas_isavailable() ||
92+
error("Error, OpenBLAS binary is missing but solve is being called. Report this issue")
8293
require_one_based_indexing(A)
8394
check && chkfinite(A)
8495
chkstride1(A)
@@ -99,6 +110,8 @@ function openblas_getrf!(A::AbstractMatrix{<:Float32};
99110
ipiv = similar(A, BlasInt, min(size(A, 1), size(A, 2))),
100111
info = Ref{BlasInt}(),
101112
check = false)
113+
__openblas_isavailable() ||
114+
error("Error, OpenBLAS binary is missing but solve is being called. Report this issue")
102115
require_one_based_indexing(A)
103116
check && chkfinite(A)
104117
chkstride1(A)
@@ -120,6 +133,8 @@ function openblas_getrs!(trans::AbstractChar,
120133
ipiv::AbstractVector{BlasInt},
121134
B::AbstractVecOrMat{<:ComplexF64};
122135
info = Ref{BlasInt}())
136+
__openblas_isavailable() ||
137+
error("Error, OpenBLAS binary is missing but solve is being called. Report this issue")
123138
require_one_based_indexing(A, ipiv, B)
124139
LinearAlgebra.LAPACK.chktrans(trans)
125140
chkstride1(A, B, ipiv)
@@ -145,6 +160,8 @@ function openblas_getrs!(trans::AbstractChar,
145160
ipiv::AbstractVector{BlasInt},
146161
B::AbstractVecOrMat{<:ComplexF32};
147162
info = Ref{BlasInt}())
163+
__openblas_isavailable() ||
164+
error("Error, OpenBLAS binary is missing but solve is being called. Report this issue")
148165
require_one_based_indexing(A, ipiv, B)
149166
LinearAlgebra.LAPACK.chktrans(trans)
150167
chkstride1(A, B, ipiv)
@@ -170,6 +187,8 @@ function openblas_getrs!(trans::AbstractChar,
170187
ipiv::AbstractVector{BlasInt},
171188
B::AbstractVecOrMat{<:Float64};
172189
info = Ref{BlasInt}())
190+
__openblas_isavailable() ||
191+
error("Error, OpenBLAS binary is missing but solve is being called. Report this issue")
173192
require_one_based_indexing(A, ipiv, B)
174193
LinearAlgebra.LAPACK.chktrans(trans)
175194
chkstride1(A, B, ipiv)
@@ -195,6 +214,8 @@ function openblas_getrs!(trans::AbstractChar,
195214
ipiv::AbstractVector{BlasInt},
196215
B::AbstractVecOrMat{<:Float32};
197216
info = Ref{BlasInt}())
217+
__openblas_isavailable() ||
218+
error("Error, OpenBLAS binary is missing but solve is being called. Report this issue")
198219
require_one_based_indexing(A, ipiv, B)
199220
LinearAlgebra.LAPACK.chktrans(trans)
200221
chkstride1(A, B, ipiv)
@@ -239,6 +260,8 @@ end
239260

240261
function SciMLBase.solve!(cache::LinearCache, alg::OpenBLASLUFactorization;
241262
kwargs...)
263+
__openblas_isavailable() ||
264+
error("Error, OpenBLAS binary is missing but solve is being called. Report this issue")
242265
A = cache.A
243266
A = convert(AbstractMatrix, A)
244267
if cache.isfresh

0 commit comments

Comments
 (0)