From af3c13c64e88d22c31b9945a52777ea20e234ff5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=BCrgen=20Fuhrmann?= Date: Thu, 15 Feb 2024 23:23:48 +0100 Subject: [PATCH 1/4] Fixes for self-installed MKL from intel oneAPI * introduces Pardiso.mkl_is_available() for use in runtests.jl * test load mkl in __init__ (like pardiso) * some link updates, hint at LD_LIBRARY_PATH --- README.md | 15 ++++++++------- deps/build.jl | 4 ++-- src/Pardiso.jl | 18 +++++++++++++++--- src/mkl_pardiso.jl | 2 +- test/runtests.jl | 6 ++++-- 5 files changed, 30 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index ee6a915..c2ee384 100644 --- a/README.md +++ b/README.md @@ -18,20 +18,21 @@ library. ### MKL PARDISO -By default Julia, will automatically install a suitable MKL for your platform. +By default Julia, will automatically install a suitable MKL for your platform by loading `MKL_jll.jl`. Note that if you use a mac you will need to pin `MKL_jll` to version 2023. -If you rather use a self installed MKL follow these instructions: +If you instead use a self installed MKL, follow these instructions: -* Set the `MKLROOT` environment variable. See the [MKL getting started - manual](https://software.intel.com/en-us/articles/intel-mkl-103-getting-started) +* Set the `MKLROOT` environment variable. See the [MKL set environment variables + manual](https://www.intel.com/content/www/us/en/docs/onemkl/developer-guide-linux/2024-0/scripts-to-set-environment-variables.html) for a thorough guide how to set this variable correctly, typically done by - executing something like `source /opt/intel/mkl/bin/mklvars.sh intel64` or + executing something like `source /opt/intel/oneapi/setvars.sh intel64` or running `"C:\Program Files (x86)\IntelSWTools\compilers_and_libraries\windows\mkl\bin\mklvars.bat" intel64` -* Run `Pkg.build("Pardiso")` +* Run `Pkg.build("Pardiso", verbose=true)` * Run `Pardiso.show_build_log()` to see the build log for additional information. -* Note that the `MKLROOT` environment variable must be set whenever using the library. +* Note that the `MKLROOT` environment variable must be set, and `LD_LIBRARY_PATH` must contain `$MKLROOT/lib` + whenever using the library. ### PARDISO 6.0 diff --git a/deps/build.jl b/deps/build.jl index cf58154..0be64a0 100644 --- a/deps/build.jl +++ b/deps/build.jl @@ -68,10 +68,10 @@ println("\nMKL Pardiso") println("=============") function find_mklparadiso() if haskey(ENV, "MKLROOT") - println("found MKLROOT environment varaible, enabling local MKL") + println("found MKLROOT environment variable, enabling local MKL") return true end - println("did not find MKLROOT environment variable, using provided MKL") + println("did not find MKLROOT environment variable, using MKL_jll") return false end diff --git a/src/Pardiso.jl b/src/Pardiso.jl index 18a40d2..a76c808 100644 --- a/src/Pardiso.jl +++ b/src/Pardiso.jl @@ -26,6 +26,8 @@ if !LOCAL_MKL_FOUND import MKL_jll end +mkl_is_available() = LOCAL_MKL_FOUND || MKL_jll.is_available() + if LinearAlgebra.BLAS.vendor() === :mkl && LinearAlgebra.BlasInt == Int64 const MklInt = Int64 const PARDISO_FUNC = :pardiso_64 @@ -109,9 +111,7 @@ const pardiso_get_schur_f = Ref{Ptr}() const PARDISO_LOADED = Ref(false) function __init__() - if MKL_jll.is_available() - libmkl_rt[] = MKL_jll.libmkl_rt_path - elseif LOCAL_MKL_FOUND + if LOCAL_MKL_FOUND if Sys.iswindows() libmkl_rt[] = "mkl_rt" elseif Sys.isapple() @@ -119,7 +119,10 @@ function __init__() else libmkl_rt[] = "libmkl_rt" end + elseif MKL_jll.is_available() + libmkl_rt[] = MKL_jll.libmkl_rt_path end + if !haskey(ENV, "PARDISOLICMESSAGE") ENV["PARDISOLICMESSAGE"] = 1 end @@ -128,6 +131,15 @@ function __init__() @warn "MKLROOT not set, MKL Pardiso solver will not be functional" end + if mkl_is_available() + try + libmklpardiso = Libdl.dlopen(libmkl_rt[]) + mklpardiso_f = Libdl.dlsym(libmklpardiso, "pardiso") + catch e + @error("MKL Pardiso did not manage to load, error thrown was: $(sprint(showerror, e))") + end + end + # This is apparently needed for MKL to not get stuck on 1 thread when # libpardiso is loaded in the block below... if libmkl_rt[] !== "" diff --git a/src/mkl_pardiso.jl b/src/mkl_pardiso.jl index ed6a1b3..b110ce5 100644 --- a/src/mkl_pardiso.jl +++ b/src/mkl_pardiso.jl @@ -13,7 +13,7 @@ mutable struct MKLPardisoSolver <: AbstractPardisoSolver end function MKLPardisoSolver() - if !MKL_jll.is_available() + if !( LOCAL_MKL_FOUND || MKL_jll.is_available()) error("MKL is not available no this platform") end pt = zeros(Int, 64) diff --git a/test/runtests.jl b/test/runtests.jl index d5b2d25..1f1c323 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -1,10 +1,12 @@ ENV["OMP_NUM_THREADS"] = 2 + using Pkg if Sys.isapple() Pkg.add(name="MKL_jll"; version = "2023") end + using Test using Pardiso using Random @@ -14,7 +16,7 @@ using LinearAlgebra Random.seed!(1234) available_solvers = empty([Pardiso.AbstractPardisoSolver]) -if Pardiso.MKL_jll.is_available() +if Pardiso.mkl_is_available() push!(available_solvers, MKLPardisoSolver) else @warn "Not testing MKL Pardiso solver" @@ -71,7 +73,7 @@ for solver in available_solvers example_hermitian_psd(solver) end -if Pardiso.MKL_jll.is_available() +if Pardiso.mkl_is_available() if Sys.CPU_THREADS >= 4 @testset "procs" begin ps = MKLPardisoSolver() From 128ff983413c73252120dc79016321d7795ad772 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=BCrgen=20Fuhrmann?= Date: Fri, 16 Feb 2024 11:49:44 +0100 Subject: [PATCH 2/4] Update src/mkl_pardiso.jl Co-authored-by: Kristoffer Carlsson --- src/mkl_pardiso.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mkl_pardiso.jl b/src/mkl_pardiso.jl index b110ce5..d081ec4 100644 --- a/src/mkl_pardiso.jl +++ b/src/mkl_pardiso.jl @@ -13,7 +13,7 @@ mutable struct MKLPardisoSolver <: AbstractPardisoSolver end function MKLPardisoSolver() - if !( LOCAL_MKL_FOUND || MKL_jll.is_available()) + if !(LOCAL_MKL_FOUND || MKL_jll.is_available()) error("MKL is not available no this platform") end pt = zeros(Int, 64) From 34d63de26582a16a9042723329a0ae87807ba54e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=BCrgen=20Fuhrmann?= Date: Fri, 16 Feb 2024 11:59:23 +0100 Subject: [PATCH 3/4] use mkl_is_available() everywher * make error msg less specific if it is not available. --- src/mkl_pardiso.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/mkl_pardiso.jl b/src/mkl_pardiso.jl index d081ec4..d33c580 100644 --- a/src/mkl_pardiso.jl +++ b/src/mkl_pardiso.jl @@ -13,8 +13,8 @@ mutable struct MKLPardisoSolver <: AbstractPardisoSolver end function MKLPardisoSolver() - if !(LOCAL_MKL_FOUND || MKL_jll.is_available()) - error("MKL is not available no this platform") + if !(mkl_is_available()) + error("MKL is not available") end pt = zeros(Int, 64) iparm = zeros(MklInt, 64) From fccea5f49dde82154305ea620257b6f2ff6317e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=BCrgen=20Fuhrmann?= Date: Fri, 16 Feb 2024 12:56:25 +0100 Subject: [PATCH 4/4] introduce MKL_LOAD_FAILED flag * set to true in __init__ if libmkl_rt cannot be loaded * checked by mkl_is_available(), so MKLPardisoSolver() cannot be instantiated if load failed --- src/Pardiso.jl | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/Pardiso.jl b/src/Pardiso.jl index a76c808..d784d45 100644 --- a/src/Pardiso.jl +++ b/src/Pardiso.jl @@ -26,7 +26,9 @@ if !LOCAL_MKL_FOUND import MKL_jll end -mkl_is_available() = LOCAL_MKL_FOUND || MKL_jll.is_available() +MKL_LOAD_FAILED = false + +mkl_is_available() = (LOCAL_MKL_FOUND || MKL_jll.is_available()) && !MKL_LOAD_FAILED if LinearAlgebra.BLAS.vendor() === :mkl && LinearAlgebra.BlasInt == Int64 const MklInt = Int64 @@ -111,6 +113,7 @@ const pardiso_get_schur_f = Ref{Ptr}() const PARDISO_LOADED = Ref(false) function __init__() + global MKL_LOAD_FAILED if LOCAL_MKL_FOUND if Sys.iswindows() libmkl_rt[] = "mkl_rt" @@ -137,6 +140,7 @@ function __init__() mklpardiso_f = Libdl.dlsym(libmklpardiso, "pardiso") catch e @error("MKL Pardiso did not manage to load, error thrown was: $(sprint(showerror, e))") + MKL_LOAD_FAILED = true end end