Skip to content

Commit

Permalink
Fixes for self-installed MKL from intel oneAPI (#99)
Browse files Browse the repository at this point in the history
* 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
* use mkl_is_available() everywhere
* make error msg less specific if it is not available.
* 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

---------

Co-authored-by: Kristoffer Carlsson <[email protected]>
  • Loading branch information
j-fu and KristofferC authored Feb 24, 2024
1 parent 5457b3f commit b64c486
Show file tree
Hide file tree
Showing 5 changed files with 35 additions and 16 deletions.
15 changes: 8 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
4 changes: 2 additions & 2 deletions deps/build.jl
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
22 changes: 19 additions & 3 deletions src/Pardiso.jl
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,10 @@ if !LOCAL_MKL_FOUND
import MKL_jll
end

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
const PARDISO_FUNC = :pardiso_64
Expand Down Expand Up @@ -109,17 +113,19 @@ 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
global MKL_LOAD_FAILED
if LOCAL_MKL_FOUND
if Sys.iswindows()
libmkl_rt[] = "mkl_rt"
elseif Sys.isapple()
libmkl_rt[] = "@rpath/libmkl_rt.dylib"
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
Expand All @@ -128,6 +134,16 @@ 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))")
MKL_LOAD_FAILED = true
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[] !== ""
Expand Down
4 changes: 2 additions & 2 deletions src/mkl_pardiso.jl
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ mutable struct MKLPardisoSolver <: AbstractPardisoSolver
end

function MKLPardisoSolver()
if !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)
Expand Down
6 changes: 4 additions & 2 deletions test/runtests.jl
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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"
Expand Down Expand Up @@ -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()
Expand Down

2 comments on commit b64c486

@KristofferC
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@JuliaRegistrator
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Registration pull request created: JuliaRegistries/General/101593

Tip: Release Notes

Did you know you can add release notes too? Just add markdown formatted text underneath the comment after the text
"Release notes:" and it will be added to the registry PR, and if TagBot is installed it will also be added to the
release that TagBot creates. i.e.

@JuliaRegistrator register

Release notes:

## Breaking changes

- blah

To add them here just re-invoke and the PR will be updated.

Tagging

After the above pull request is merged, it is recommended that a tag is created on this repository for the registered package version.

This will be done automatically if the Julia TagBot GitHub Action is installed, or can be done manually through the github interface, or via:

git tag -a v0.5.5 -m "<description of version>" b64c4867fefaaf715c50403a49f36c07c1c92170
git push origin v0.5.5

Please sign in to comment.