-
Notifications
You must be signed in to change notification settings - Fork 56
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Require Julia 1.6+, use Preferences, eliminate mutable state
This adds support for `Preferences.jl` as the backing store for setting a computation backend (currently only supports `fftw` and `mkl` as valid choices). The convenience method `set_provider!()` is given, but it is little more than a wrapper around `Preferences.set_preferences!()`. Users can alter their `LocalPreferences.toml` or `Project.toml` files by hand as well; in the event that an illegal value is provided, an error will be displayed and `fftw` will be chosen as the default value. Preferences is a relatively new subsystem in Julia and it has some lacking support in `Pkg`; so for now we are adding a separate `test/Project.toml`, which will have preferences added into it on CI, as there is a bug in propagating preferences when a single `Project.toml` is used with extra dependencies for the tests.
- Loading branch information
1 parent
07eeabb
commit 3e2eebb
Showing
9 changed files
with
139 additions
and
106 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
#!/usr/bin/env julia | ||
|
||
open(joinpath(dirname(@__DIR__), "test", "Project.toml"), "a") do io | ||
println(io, """ | ||
[preferences.FFTW] | ||
provider = "$(ARGS[1])" | ||
""") | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
|
||
function get_provider() | ||
# Note: we CANNOT do something like have the `default` value be `get(ENV, "JULIA_FFTW_PROVIDER", "fftw")` here. | ||
# This is because the only way the Julia knows that a default has changed is if the values on-disk change; so | ||
# if your "default" value can be changed from the outside, you quickly run into cache invalidation issues. | ||
# So the default here _must_ be a constant. | ||
default_provider = "fftw" | ||
|
||
# Load the preference | ||
provider = @load_preference("provider", default_provider) | ||
|
||
# Ensure the provider matches one of the ones we support | ||
if provider ∉ ("fftw", "mkl") | ||
@error("Invalid provider setting \"$(provider)\"; valid settings include [\"fftw\", \"mkl\"], defaulting to \"fftw\"") | ||
provider = default_provider | ||
end | ||
return provider | ||
end | ||
|
||
# Read in preferences, see if any users have requested a particular backend | ||
const fftw_provider = get_provider() | ||
|
||
""" | ||
set_provider!(provider; export_prefs::Bool = false) | ||
Convenience wrapper for setting the FFT provider. Valid values include `"fftw"`, `"mkl"`. | ||
Also supports `Preferences` sentinel values `nothing` and `missing`; see the docstring for | ||
`Preferences.set_preferences!()` for more information on what these values mean. | ||
""" | ||
function set_provider!(provider; export_prefs::Bool = false) | ||
if provider !== nothing && provider !== missing && provider ∉ ("fftw", "mkl") | ||
throw(ArgumentError("Invalid provider value '$(provider)'")) | ||
end | ||
set_preferences!(@__MODULE__, "provider" => provider; export_prefs) | ||
if provider != fftw_provider | ||
# Re-fetch to get default values in the event that `nothing` or `missing` was passed in. | ||
provider = get_provider() | ||
@info("FFTW provider changed; restart Julia for this change to take effect", provider) | ||
end | ||
end | ||
|
||
# If we're using fftw_jll, load it in | ||
@static if fftw_provider == "fftw" | ||
using FFTW_jll | ||
|
||
# callback function that FFTW uses to launch `num` parallel | ||
# tasks (FFTW/fftw3#175): | ||
function spawnloop(f::Ptr{Cvoid}, fdata::Ptr{Cvoid}, elsize::Csize_t, num::Cint, callback_data::Ptr{Cvoid}) | ||
@sync for i = 0:num-1 | ||
Threads.@spawn ccall(f, Ptr{Cvoid}, (Ptr{Cvoid},), fdata + elsize*i) | ||
end | ||
end | ||
|
||
# If FFTW was built with threads, then they must be initialized before any FFTW planning routine. | ||
# -- This initializes FFTW's threads support (defaulting to 1 thread). | ||
# If this isn't called before the FFTW planner is created, then | ||
# FFTW's threads algorithms won't be registered or used at all. | ||
# (Previously, we called fftw_cleanup, but this invalidated existing | ||
# plans, causing Base Julia issue #19892.) | ||
function fftw_init_threads() | ||
stat = ccall((:fftw_init_threads, libfftw3), Int32, ()) | ||
statf = ccall((:fftwf_init_threads, libfftw3f), Int32, ()) | ||
if stat == 0 || statf == 0 | ||
error("could not initialize FFTW threads") | ||
end | ||
|
||
if nthreads() > 1 | ||
cspawnloop = @cfunction(spawnloop, Cvoid, (Ptr{Cvoid}, Ptr{Cvoid}, Csize_t, Cint, Ptr{Cvoid})) | ||
ccall((:fftw_threads_set_callback, libfftw3), Cvoid, (Ptr{Cvoid}, Ptr{Cvoid}), cspawnloop, C_NULL) | ||
ccall((:fftwf_threads_set_callback, libfftw3f), Cvoid, (Ptr{Cvoid}, Ptr{Cvoid}), cspawnloop, C_NULL) | ||
end | ||
end | ||
end | ||
|
||
# If we're using MKL, load it in and set library paths appropriately. | ||
@static if fftw_provider == "mkl" | ||
using IntelOpenMP_jll, MKL_jll | ||
const libfftw3 = MKL_jll.libmkl_rt_path | ||
const libfftw3f = libfftw3 | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
# A bug in Julia 1.6.0's Pkg causes Preferences to be dropped during `Pkg.test()`, so we work around | ||
# it by explicitly creating a `test/Project.toml` which will correctly communicate any preferences | ||
# through to the child Julia process. X-ref: https://github.com/JuliaLang/Pkg.jl/issues/2500 | ||
|
||
[deps] | ||
AbstractFFTs = "621f4979-c628-5d54-868e-fcf4e3e8185c" | ||
FFTW_jll = "f5851436-0d7a-5f13-b9de-f02708fd171a" | ||
IntelOpenMP_jll = "1d5cc7b8-4909-519e-a0f8-d0f5ad9712d0" | ||
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" | ||
Reexport = "189a3867-3050-52da-a836-e630ba90ab69" | ||
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters