From 09ff74481b6a8efcdf68d4598a3d5cdcf227e906 Mon Sep 17 00:00:00 2001 From: "Steven G. Johnson" Date: Tue, 30 Jul 2019 15:15:38 -0400 Subject: [PATCH 1/4] partr thread support --- .travis.yml | 1 + deps/build_fftw.jl | 54 ++++++++++++++++++++++++---------------------- src/FFTW.jl | 27 ++++++++++++++++++++++- 3 files changed, 55 insertions(+), 27 deletions(-) diff --git a/.travis.yml b/.travis.yml index 25986b9..dca7189 100644 --- a/.travis.yml +++ b/.travis.yml @@ -11,6 +11,7 @@ env: matrix: - JULIA_FFTW_PROVIDER=FFTW - JULIA_FFTW_PROVIDER=MKL + - JULIA_NUM_THREADS=2 notifications: email: false # uncomment the following lines to override the default test script diff --git a/deps/build_fftw.jl b/deps/build_fftw.jl index 05a73ef..e676534 100644 --- a/deps/build_fftw.jl +++ b/deps/build_fftw.jl @@ -4,44 +4,46 @@ using BinaryProvider # requires BinaryProvider 0.3.0 or later const verbose = "--verbose" in ARGS const prefix = Prefix(get([a for a in ARGS if a != "--verbose"], 1, joinpath(@__DIR__, "usr"))) products = [ - LibraryProduct(prefix, String["libfftw3"], :libfftw3), - LibraryProduct(prefix, String["libfftw3f"], :libfftw3f), + LibraryProduct(prefix, ["libfftw3"], :libfftw3), + LibraryProduct(prefix, ["libfftw3f"], :libfftw3f), ] # Download binaries from hosted location -bin_prefix = "https://github.com/JuliaMath/FFTWBuilder/releases/download/v3.3.8+1" +bin_prefix = "https://github.com/JuliaMath/FFTWBuilder/releases/download/v3.3.9-alpha1+1" # Listing of files generated by BinaryBuilder: download_info = Dict( - Linux(:aarch64, :glibc) => ("$bin_prefix/FFTW.aarch64-linux-gnu.tar.gz", "4296ad9af20d4441fd809c6aaa3ee5fa36818b7a2eb3372da7d2ead454b4e570"), - Linux(:aarch64, :musl) => ("$bin_prefix/FFTW.aarch64-linux-musl.tar.gz", "ef6d4e56bd9e405ef2895a857ffbc07cb7abcf450040a2335b83a95f4a431392"), - Linux(:armv7l, :glibc, :eabihf) => ("$bin_prefix/FFTW.arm-linux-gnueabihf.tar.gz", "8f8c69a6eca468465734e1fd58801519cea0f7a8f9e08bba93e39315758f7a7c"), - Linux(:armv7l, :musl, :eabihf) => ("$bin_prefix/FFTW.arm-linux-musleabihf.tar.gz", "48d137fddab6888bdc59893d22728f081578ff0884954f0f6f5df51afff53ece"), - Linux(:i686, :glibc) => ("$bin_prefix/FFTW.i686-linux-gnu.tar.gz", "76d85d81a81752a0e08bc2eec51a568a6000928a550c37a181b51340452b1b5f"), - Linux(:i686, :musl) => ("$bin_prefix/FFTW.i686-linux-musl.tar.gz", "5ee42df3aa002e9511c3cc808f728429e4930bb24df8b461dc137bf49aa71b8f"), - Windows(:i686) => ("$bin_prefix/FFTW.i686-w64-mingw32.tar.gz", "28b96cb5d78c87d16d305a63a838c5027d319c0292f00c925e14f21c744535a8"), - Linux(:powerpc64le, :glibc) => ("$bin_prefix/FFTW.powerpc64le-linux-gnu.tar.gz", "53d305eebb3a152df093d637fe8a4d6288a2b7175bf91ab9242dad62e5e0853a"), - MacOS(:x86_64) => ("$bin_prefix/FFTW.x86_64-apple-darwin14.tar.gz", "7562aed6279ea965435c8a388be1494b9a18f7e00058d0fa260a711bffde1bd5"), - Linux(:x86_64, :glibc) => ("$bin_prefix/FFTW.x86_64-linux-gnu.tar.gz", "70dcc7ad2697121564d5d91da9f2544b0e68b026779a45063039a39cd5585711"), - Linux(:x86_64, :musl) => ("$bin_prefix/FFTW.x86_64-linux-musl.tar.gz", "4bf1c1e7489241c38788bc061f2a091fe72605f67e58411b2933313fa0923877"), - FreeBSD(:x86_64) => ("$bin_prefix/FFTW.x86_64-unknown-freebsd11.1.tar.gz", "ad70aca12821f6df1c67da74fc2f1b4fa009ac14d8570ff1f912876e731185af"), - Windows(:x86_64) => ("$bin_prefix/FFTW.x86_64-w64-mingw32.tar.gz", "6726bff25faeca8e29dfce8be5b0fb7da0a380faa9fdb5a5a6c98ea76d009b2f"), + Linux(:aarch64, libc=:glibc) => ("$bin_prefix/FFTW.v3.3.9-alpha1.aarch64-linux-gnu.tar.gz", "f1eb8ad7889fe370c4201a66d47b2e0615550e507fae7681416ce2aea5345918"), + Linux(:aarch64, libc=:musl) => ("$bin_prefix/FFTW.v3.3.9-alpha1.aarch64-linux-musl.tar.gz", "60422edf3c0b7800f8b46dbd91a23296bce0f406351a0430ab94cbc2b89f500c"), + Linux(:armv7l, libc=:glibc, call_abi=:eabihf) => ("$bin_prefix/FFTW.v3.3.9-alpha1.arm-linux-gnueabihf.tar.gz", "28baca9720095a5ba21941e4bd1f9426b9a59fc074a9b64f18e1a6199a0944ee"), + Linux(:armv7l, libc=:musl, call_abi=:eabihf) => ("$bin_prefix/FFTW.v3.3.9-alpha1.arm-linux-musleabihf.tar.gz", "70cb66a82f92427f5397d2dddcef251696d80b90ac1e00b68bd8429101f00fd0"), + Linux(:i686, libc=:glibc) => ("$bin_prefix/FFTW.v3.3.9-alpha1.i686-linux-gnu.tar.gz", "78c8144081ea5ce1bb954bf5ae8c3821eaf61910798205e700773219770d7648"), + Linux(:i686, libc=:musl) => ("$bin_prefix/FFTW.v3.3.9-alpha1.i686-linux-musl.tar.gz", "f2c9a0234a046411532f99c8ef0d2f3bcf7e2f8b42b540aaade060a5771eb06d"), + Windows(:i686) => ("$bin_prefix/FFTW.v3.3.9-alpha1.i686-w64-mingw32.tar.gz", "522dfeec872b9cbab99b34f83591be58e4a705910a20631e3c28137776342f51"), + Linux(:powerpc64le, libc=:glibc) => ("$bin_prefix/FFTW.v3.3.9-alpha1.powerpc64le-linux-gnu.tar.gz", "5c221b796fc26e34d846ae6b380b2d506bd1f179b9e95542fb132300d2f734ee"), + MacOS(:x86_64) => ("$bin_prefix/FFTW.v3.3.9-alpha1.x86_64-apple-darwin14.tar.gz", "3b3d886bba184a069bd4c8ff80c9b05baa70c72e66c7f144270b58c3488d504b"), + Linux(:x86_64, libc=:glibc) => ("$bin_prefix/FFTW.v3.3.9-alpha1.x86_64-linux-gnu.tar.gz", "5852eb0cfe0a2eee9ae92806dfc414d73a2c2015ad551d76f764787c34b56e26"), + Linux(:x86_64, libc=:musl) => ("$bin_prefix/FFTW.v3.3.9-alpha1.x86_64-linux-musl.tar.gz", "57d5f470e2865c6ae61243b0b914572bb623d9961ccbc1fd448aeca0bbddaca0"), + FreeBSD(:x86_64) => ("$bin_prefix/FFTW.v3.3.9-alpha1.x86_64-unknown-freebsd11.1.tar.gz", "5be6e6207ba377ae818143e1e2789f83085725e4536e67ce6852762143c2a138"), + Windows(:x86_64) => ("$bin_prefix/FFTW.v3.3.9-alpha1.x86_64-w64-mingw32.tar.gz", "1d8657df9f42eae29e89434630fe8792cf07c88d69c6f32fb2fa464f08c779da"), ) # Install unsatisfied or updated dependencies: unsatisfied = any(!satisfied(p; verbose=verbose) for p in products) -if haskey(download_info, platform_key()) - url, tarball_hash = download_info[platform_key()] - if unsatisfied || !isinstalled(url, tarball_hash; prefix=prefix) - # Download and install binaries - install(url, tarball_hash; prefix=prefix, force=true, verbose=verbose) - end -elseif unsatisfied - # If we don't have a BinaryProvider-compatible .tar.gz to download, complain. +dl_info = choose_download(download_info, platform_key_abi()) +if dl_info === nothing && unsatisfied + # If we don't have a compatible .tar.gz to download, complain. # Alternatively, you could attempt to install from a separate provider, # build from source or something even more ambitious here. - error("Your platform $(triplet(platform_key())) is not supported by this package!") + error("Your platform (\"$(Sys.MACHINE)\", parsed as \"$(triplet(platform_key_abi()))\") is not supported by this package!") +end + +# If we have a download, and we are unsatisfied (or the version we're +# trying to install is not itself installed) then load it up! +if unsatisfied || !isinstalled(dl_info...; prefix=prefix) + # Download and install binaries + install(dl_info...; prefix=prefix, force=true, verbose=verbose) end # Write out a deps.jl file that will contain mappings for our products -write_deps_file(joinpath(@__DIR__, "deps.jl"), products) +write_deps_file(joinpath(@__DIR__, "deps.jl"), products, verbose=verbose) diff --git a/src/FFTW.jl b/src/FFTW.jl index c65dd5a..afd5d92 100644 --- a/src/FFTW.jl +++ b/src/FFTW.jl @@ -25,6 +25,17 @@ end # MKL provides its own FFTW const fftw_vendor = occursin("libmkl_rt", libfftw3) ? :mkl : :fftw +# Use Julia partr threading backend if present +@static if fftw_vendor == :fftw && isdefined(Threads, Symbol("@spawn")) + # 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 +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 @@ -33,11 +44,25 @@ const fftw_vendor = occursin("libmkl_rt", libfftw3) ? :mkl : :fftw # plans, causing Base Julia issue #19892.) function __init__() check_deps() - stat = ccall((:fftw_init_threads, libfftw3), Int32, ()) + 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 + @static if fftw_vendor == :fftw + if Threads.nthreads() > 1 # number of Julia threads is set when Julia is launched + ccall((:fftw_make_planner_thread_safe, libfftw3), Cvoid, ()) + ccall((:fftwf_make_planner_thread_safe, libfftw3f), Cvoid, ()) + end + @static if isdefined(Threads, Symbol("@spawn")) + if Threads.nthreads() > 1 # partr will give us our threads + 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) + set_num_threads(Threads.nthreads() * 4) # spawn more tasks than threads to help load-balancing + end + end + end end include("fft.jl") From 37cb9c6f3e367edb7829095531eb59d0fdded5a5 Mon Sep 17 00:00:00 2001 From: "Steven G. Johnson" Date: Wed, 4 Sep 2019 21:50:38 -0400 Subject: [PATCH 2/4] switch to Yggdrasil build --- deps/build_fftw.jl | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/deps/build_fftw.jl b/deps/build_fftw.jl index e676534..2fff916 100644 --- a/deps/build_fftw.jl +++ b/deps/build_fftw.jl @@ -4,28 +4,28 @@ using BinaryProvider # requires BinaryProvider 0.3.0 or later const verbose = "--verbose" in ARGS const prefix = Prefix(get([a for a in ARGS if a != "--verbose"], 1, joinpath(@__DIR__, "usr"))) products = [ - LibraryProduct(prefix, ["libfftw3"], :libfftw3), - LibraryProduct(prefix, ["libfftw3f"], :libfftw3f), + LibraryProduct(["libfftw3"], :libfftw3), + LibraryProduct(["libfftw3f"], :libfftw3f), ] # Download binaries from hosted location -bin_prefix = "https://github.com/JuliaMath/FFTWBuilder/releases/download/v3.3.9-alpha1+1" +bin_prefix = "https://github.com/JuliaBinaryWrappers/FFTW_jll.jl/releases/download/FFTW-v3.3.9+0" # Listing of files generated by BinaryBuilder: download_info = Dict( - Linux(:aarch64, libc=:glibc) => ("$bin_prefix/FFTW.v3.3.9-alpha1.aarch64-linux-gnu.tar.gz", "f1eb8ad7889fe370c4201a66d47b2e0615550e507fae7681416ce2aea5345918"), - Linux(:aarch64, libc=:musl) => ("$bin_prefix/FFTW.v3.3.9-alpha1.aarch64-linux-musl.tar.gz", "60422edf3c0b7800f8b46dbd91a23296bce0f406351a0430ab94cbc2b89f500c"), - Linux(:armv7l, libc=:glibc, call_abi=:eabihf) => ("$bin_prefix/FFTW.v3.3.9-alpha1.arm-linux-gnueabihf.tar.gz", "28baca9720095a5ba21941e4bd1f9426b9a59fc074a9b64f18e1a6199a0944ee"), - Linux(:armv7l, libc=:musl, call_abi=:eabihf) => ("$bin_prefix/FFTW.v3.3.9-alpha1.arm-linux-musleabihf.tar.gz", "70cb66a82f92427f5397d2dddcef251696d80b90ac1e00b68bd8429101f00fd0"), - Linux(:i686, libc=:glibc) => ("$bin_prefix/FFTW.v3.3.9-alpha1.i686-linux-gnu.tar.gz", "78c8144081ea5ce1bb954bf5ae8c3821eaf61910798205e700773219770d7648"), - Linux(:i686, libc=:musl) => ("$bin_prefix/FFTW.v3.3.9-alpha1.i686-linux-musl.tar.gz", "f2c9a0234a046411532f99c8ef0d2f3bcf7e2f8b42b540aaade060a5771eb06d"), - Windows(:i686) => ("$bin_prefix/FFTW.v3.3.9-alpha1.i686-w64-mingw32.tar.gz", "522dfeec872b9cbab99b34f83591be58e4a705910a20631e3c28137776342f51"), - Linux(:powerpc64le, libc=:glibc) => ("$bin_prefix/FFTW.v3.3.9-alpha1.powerpc64le-linux-gnu.tar.gz", "5c221b796fc26e34d846ae6b380b2d506bd1f179b9e95542fb132300d2f734ee"), - MacOS(:x86_64) => ("$bin_prefix/FFTW.v3.3.9-alpha1.x86_64-apple-darwin14.tar.gz", "3b3d886bba184a069bd4c8ff80c9b05baa70c72e66c7f144270b58c3488d504b"), - Linux(:x86_64, libc=:glibc) => ("$bin_prefix/FFTW.v3.3.9-alpha1.x86_64-linux-gnu.tar.gz", "5852eb0cfe0a2eee9ae92806dfc414d73a2c2015ad551d76f764787c34b56e26"), - Linux(:x86_64, libc=:musl) => ("$bin_prefix/FFTW.v3.3.9-alpha1.x86_64-linux-musl.tar.gz", "57d5f470e2865c6ae61243b0b914572bb623d9961ccbc1fd448aeca0bbddaca0"), - FreeBSD(:x86_64) => ("$bin_prefix/FFTW.v3.3.9-alpha1.x86_64-unknown-freebsd11.1.tar.gz", "5be6e6207ba377ae818143e1e2789f83085725e4536e67ce6852762143c2a138"), - Windows(:x86_64) => ("$bin_prefix/FFTW.v3.3.9-alpha1.x86_64-w64-mingw32.tar.gz", "1d8657df9f42eae29e89434630fe8792cf07c88d69c6f32fb2fa464f08c779da"), + Linux(:aarch64, libc=:glibc) => ("$bin_prefix/FFTW.v3.3.9.aarch64-linux-gnu.tar.gz", "70a68ce1e89536a8ee8df427de28f527c69d31f28cd223ebf8cf7402f3b45e50"), + Linux(:aarch64, libc=:musl) => ("$bin_prefix/FFTW.v3.3.9.aarch64-linux-musl.tar.gz", "a51a44344e0e99ebde48b20495a2c44aeefa51b39a2160932c9cf267d14aa6cf"), + Linux(:armv7l, libc=:glibc, call_abi=:eabihf) => ("$bin_prefix/FFTW.v3.3.9.arm-linux-gnueabihf.tar.gz", "2ee40e4d2561f656366eb147213ed483bfd4d3b63ef07359a361ccda48baca94"), + Linux(:armv7l, libc=:musl, call_abi=:eabihf) => ("$bin_prefix/FFTW.v3.3.9.arm-linux-musleabihf.tar.gz", "c869cdf7bf12c4f6d4d3359a1c6f14ec59ac84dc96672495f730a30800489b9e"), + Linux(:i686, libc=:glibc) => ("$bin_prefix/FFTW.v3.3.9.i686-linux-gnu.tar.gz", "651f7d53dea2b95ae26799f352bea8bd4c17e4371c8faeb3cbb37db9d17b2a84"), + Linux(:i686, libc=:musl) => ("$bin_prefix/FFTW.v3.3.9.i686-linux-musl.tar.gz", "9f731365440b19edb8e462a59174a20c2f27df83ab55a2c1e6e4edcbb40a132d"), + Windows(:i686) => ("$bin_prefix/FFTW.v3.3.9.i686-w64-mingw32.tar.gz", "644422a04bfa8c74a8cc7b3750083e645a632c80ce03f69a7cc912ee6cf91552"), + Linux(:powerpc64le, libc=:glibc) => ("$bin_prefix/FFTW.v3.3.9.powerpc64le-linux-gnu.tar.gz", "ab5f703b110f8af01796e7f31cd11082c7bb27d7184b07f5e8da939dd1b0f2fd"), + MacOS(:x86_64) => ("$bin_prefix/FFTW.v3.3.9.x86_64-apple-darwin14.tar.gz", "1f4f99aadb78adc4a0d7df10097a1291c478355255bdd61979b5cdd116f56dac"), + Linux(:x86_64, libc=:glibc) => ("$bin_prefix/FFTW.v3.3.9.x86_64-linux-gnu.tar.gz", "ed7fbfe6abd31ba5e47569ff1ebc6b754d7adfdbc9f27478634de495dbc54d32"), + Linux(:x86_64, libc=:musl) => ("$bin_prefix/FFTW.v3.3.9.x86_64-linux-musl.tar.gz", "35babebbb69d0bdcb8865372dcbeee3f5cd690cd470be148afd4ea6cec5015c0"), + FreeBSD(:x86_64) => ("$bin_prefix/FFTW.v3.3.9.x86_64-unknown-freebsd11.1.tar.gz", "6ff38bce55886dc4d7cf875f17bbec2b2ffa5b5eb54389ef9c5d8461f4e40c82"), + Windows(:x86_64) => ("$bin_prefix/FFTW.v3.3.9.x86_64-w64-mingw32.tar.gz", "6793204f0d51a99948fa7983d798c2cbfa696df6e2e5452253ad874fe47b3143"), ) # Install unsatisfied or updated dependencies: From 8ffd30a25b14b68afdda082c0de8c23ed96f4138 Mon Sep 17 00:00:00 2001 From: Elliot Saba Date: Wed, 4 Sep 2019 22:41:26 -0700 Subject: [PATCH 3/4] Fix problem in build_fftw.jl --- deps/build_fftw.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/deps/build_fftw.jl b/deps/build_fftw.jl index 2fff916..e6bf0b7 100644 --- a/deps/build_fftw.jl +++ b/deps/build_fftw.jl @@ -4,8 +4,8 @@ using BinaryProvider # requires BinaryProvider 0.3.0 or later const verbose = "--verbose" in ARGS const prefix = Prefix(get([a for a in ARGS if a != "--verbose"], 1, joinpath(@__DIR__, "usr"))) products = [ - LibraryProduct(["libfftw3"], :libfftw3), - LibraryProduct(["libfftw3f"], :libfftw3f), + LibraryProduct(prefix, ["libfftw3"], :libfftw3), + LibraryProduct(prefix, ["libfftw3f"], :libfftw3f), ] # Download binaries from hosted location From ef1019cde989856a0352f8b2670bd08cca6906f7 Mon Sep 17 00:00:00 2001 From: "Steven G. Johnson" Date: Thu, 5 Sep 2019 07:32:08 -0400 Subject: [PATCH 4/4] move threads check to end (since threads are now initialized in __init__) and explicitly call set_num_threads(1) for no-threads check since multithreaded Julia now uses multiple FFTW threads by default --- test/runtests.jl | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/test/runtests.jl b/test/runtests.jl index 204392b..696fe0c 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -5,20 +5,6 @@ using AbstractFFTs: Plan, plan_inv using Test using LinearAlgebra -# Base Julia issue #19892 -# (test this first to make sure it happens before set_num_threads) -let a = randn(10^5,1), p1 = plan_rfft(a, flags=FFTW.ESTIMATE) - FFTW.set_num_threads(2) - p2 = plan_rfft(a, flags=FFTW.ESTIMATE) - @test p1*a ≈ p2*a - # make sure threads are actually being used for p2 - # (tests #21163). - if FFTW.has_sprint_plan - @test !occursin("dft-thr", string(p1)) - @test occursin("dft-thr", string(p2)) - end -end - # fft a = rand(8) + im*rand(8) @test norm(ifft(fft(a)) - a) < 1e-8 @@ -516,3 +502,18 @@ let A = rand(Float32, 35), Ac = rand(Complex{Float32}, 35) @test_throws ArgumentError plan_fft(Array{Complex{Float32}}(undef, 32)) * view(Ac, 2:33) end end + +# Base Julia issue #19892 +let a = randn(10^5,1) + FFTW.set_num_threads(1) + p1 = plan_rfft(a, flags=FFTW.ESTIMATE) + FFTW.set_num_threads(2) + p2 = plan_rfft(a, flags=FFTW.ESTIMATE) + @test p1*a ≈ p2*a + # make sure threads are actually being used for p2 + # (tests #21163). + if FFTW.has_sprint_plan + @test !occursin("dft-thr", string(p1)) + @test occursin("dft-thr", string(p2)) + end +end