Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add mkl_path preference to support using "system" MKL #84

Draft
wants to merge 16 commits into
base: master
Choose a base branch
from
2 changes: 2 additions & 0 deletions Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,12 @@ Artifacts = "56f22d72-fd6d-98f1-02f0-08ddc0907c33"
Libdl = "8f399da3-3557-5675-b5ff-fb832c97cbdb"
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
MKL_jll = "856f044c-d86e-5d09-b602-aeab76dc8ba7"
Preferences = "21216c6a-2e73-6563-6e65-726566657250"
carstenbauer marked this conversation as resolved.
Show resolved Hide resolved

[compat]
MKL_jll = "2022.1"
julia = "1.8"
Preferences = "1.4"

[extras]
Dates = "ade2ca70-3891-5945-98fb-dc099432e06a"
Expand Down
27 changes: 20 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,23 @@

MKL.jl is a Julia package that allows users to use the Intel MKL library for Julia's underlying BLAS and LAPACK, instead of OpenBLAS, which Julia ships with by default. Julia includes [libblastrampoline](https://github.com/staticfloat/libblastrampoline), which enables picking a BLAS and LAPACK library at runtime. A [JuliaCon 2021 talk](https://www.youtube.com/watch?v=t6hptekOR7s) provides details on this mechanism.

This package requires Julia 1.7+
This package requires Julia 1.7+.

## Usage

If you want to use `MKL.jl` in your project, make sure it is the first package you load before any other package. It is essential that MKL be loaded before other packages so that it can find the Intel OMP library and avoid [issues resulting out of GNU OMP being loaded first](https://github.com/JuliaPackaging/BinaryBuilder.jl/issues/700).
## Installation

## To Install:
To install the package execute

Adding the package will replace the system BLAS and LAPACK with MKL provided ones at runtime. Note that the MKL package has to be loaded in every new Julia process. Upon quitting and restarting, Julia will start with the default OpenBLAS.
```julia
julia> using Pkg; Pkg.add("MKL")
```

## To Check Installation:
## Usage

Loading the package (`using MKL`) will replace the system BLAS and LAPACK with MKL provided ones at runtime. Make sure it is the first package you load before any other package. It is essential that MKL be loaded before other packages so that it can find the Intel OMP library and avoid [issues resulting out of GNU OMP being loaded first](https://github.com/JuliaPackaging/BinaryBuilder.jl/issues/700).

Note that the MKL package has to be loaded in every new Julia process. Upon quitting and restarting, Julia will start with the default OpenBLAS.

## Check

```julia
julia> using LinearAlgebra
Expand All @@ -35,6 +38,16 @@ Libraries:
└ [ILP64] libmkl_rt.1.dylib
```

Note that you can put `using MKL` into your `startup.jl` to make Julia automatically use Intel MKL in every session.

## Using the 64-bit vs 32-bit version of MKL

We use ILP64 by default on 64-bit systems, and LP64 on 32-bit systems.

## Using a system-provided Intel MKL

If you want to use a system-provided Intel MKL installation, you can set the [preference](https://github.com/JuliaPackaging/Preferences.jl) `mkl_path` to hint MKL.jl to the corresponding `libmkl_rt` library. Specifically, the options are:

* `mkl_jll` (default): Download and install MKL via [MKL_jll.jl](https://github.com/JuliaBinaryWrappers/MKL_jll.jl).
* `system`: The package will try to automatically locate the system-provided libmkl_rt library (i.e. find it on the linker search path).
* `path/to/my/libmkl_rt.<EXT>`: Explicit path to the `libmkl_rt.<EXT>` where `<EXT>` is the shared library extension of the system at hand (e.g. `.so`, `.dll`, `.dylib`)
39 changes: 37 additions & 2 deletions src/MKL.jl
Original file line number Diff line number Diff line change
@@ -1,6 +1,41 @@
module MKL

using MKL_jll
using Preferences
using Libdl
using LinearAlgebra

# Choose an MKL path; taking an explicit preference as the first choice,
# but if nothing is set as a preference, fall back to the default choice of `MKL_jll`.
const mkl_path = something(
@load_preference("mkl_path", nothing),
"mkl_jll",
)::String

if lowercase(mkl_path) == "mkl_jll"
# Only load MKL_jll if we are suppoed to use it as the MKL source
# to avoid an unnecessary download of the (lazy) artifact.
import MKL_jll
const libmkl_rt = MKL_jll.libmkl_rt
elseif lowercase(mkl_path) == "system"
# We expect the "system" MKL to already be loaded,
# or be on our linker search path.
libname = string("libmkl_rt", ".", Libdl.dlext)
const libmkl_rt = find_library(libname, [""])
libmkl_rt == "" && error("Couldn't find $libname. Try to specify the path to `libmkl_rt` explicitly.")
else
# mkl_path should be a valid path to libmkl_rt.
const libmkl_rt = mkl_path
isfile(libmkl_rt) || error("Couldn't find MKL library at $libmkl_rt.")
carstenbauer marked this conversation as resolved.
Show resolved Hide resolved
end

# Changing the MKL provider/path preference
function set_mkl_path(path)
if lowercase(path) ∉ ("mkl_jll", "system")
isfile(path) || error("The provided argument $path doesn't seem to be a valid path to libmkl_rt.")
end
@set_preferences!("mkl_path" => path)
@info("New MKL preference set; please restart Julia to see this take effect", path)
staticfloat marked this conversation as resolved.
Show resolved Hide resolved
end

using LinearAlgebra

Expand Down Expand Up @@ -37,7 +72,7 @@ function set_interface_layer(interface::Interface = INTERFACE_LP64)
end

function __init__()
if MKL_jll.is_available()
if !(mkl_path == "mkl_jll" && !MKL_jll.is_available())
carstenbauer marked this conversation as resolved.
Show resolved Hide resolved
if Sys.isapple()
set_threading_layer(THREADING_SEQUENTIAL)
end
Expand Down