From bea54cc72b9411b89b99777f605b282f5d4b5bed Mon Sep 17 00:00:00 2001 From: Jan Weidner Date: Fri, 19 Jun 2020 14:06:38 +0200 Subject: [PATCH 01/30] add BLAS.get_num_threads --- stdlib/LinearAlgebra/src/blas.jl | 24 ++++++++++++++++++++---- stdlib/LinearAlgebra/test/blas.jl | 11 +++++++++++ 2 files changed, 31 insertions(+), 4 deletions(-) diff --git a/stdlib/LinearAlgebra/src/blas.jl b/stdlib/LinearAlgebra/src/blas.jl index a2367d7ee4b90..6385b24f90dac 100644 --- a/stdlib/LinearAlgebra/src/blas.jl +++ b/stdlib/LinearAlgebra/src/blas.jl @@ -113,10 +113,8 @@ Set the number of threads the BLAS library should use. """ function set_num_threads(n::Integer) blas = vendor() - if blas === :openblas - return ccall((:openblas_set_num_threads, libblas), Cvoid, (Int32,), n) - elseif blas === :openblas64 - return ccall((:openblas_set_num_threads64_, libblas), Cvoid, (Int32,), n) + if blas === :openblas || blas == :openblas64 + return ccall((@blasfunc(openblas_set_num_threads), libblas), Cvoid, (Int32,), n) elseif blas === :mkl # MKL may let us set the number of threads in several ways return ccall((:MKL_Set_Num_Threads, libblas), Cvoid, (Cint,), n) @@ -130,6 +128,24 @@ function set_num_threads(n::Integer) return nothing end +""" + get_num_threads() + +Get the number of threads the BLAS library is using. +""" +function get_num_threads() + blas = LinearAlgebra.BLAS.vendor() + if blas === :openblas || blas === :openblas64 + return ccall((@blasfunc(openblas_get_num_threads), libblas), Cint, ()) + elseif blas == :mkl + return ccall((:MKL_Get_Max_Num_Threads, libblas), Cint, ()) + elseif Sys.isapple() + return Base.parse(Cint, ENV["VECLIB_MAXIMUM_THREADS"]) + else + error("Unknown BLAS") # better error? return nothing + end +end + const _testmat = [1.0 0.0; 0.0 -1.0] function check() blas = vendor() diff --git a/stdlib/LinearAlgebra/test/blas.jl b/stdlib/LinearAlgebra/test/blas.jl index 23c6d68cdc997..e6a4a4d758781 100644 --- a/stdlib/LinearAlgebra/test/blas.jl +++ b/stdlib/LinearAlgebra/test/blas.jl @@ -553,4 +553,15 @@ Base.stride(A::WrappedArray, i::Int) = stride(A.A, i) end end +@testset "get_set_num_threads" begin + default = BLAS.get_num_threads() + @test default isa Integer + @test default > 0 + new = rand(1:10) + BLAS.set_num_threads(net) + @test BLAS.get_num_threads() == new + BLAS.set_num_threads(default) + @test BLAS.get_num_threads() == default +end + end # module TestBLAS From 2de23cdcce75635cc6fb45b150bc509e1f53c656 Mon Sep 17 00:00:00 2001 From: Jan Weidner Date: Fri, 19 Jun 2020 14:11:39 +0200 Subject: [PATCH 02/30] fix --- stdlib/LinearAlgebra/src/blas.jl | 2 +- stdlib/LinearAlgebra/test/blas.jl | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/stdlib/LinearAlgebra/src/blas.jl b/stdlib/LinearAlgebra/src/blas.jl index 6385b24f90dac..85d42251b3321 100644 --- a/stdlib/LinearAlgebra/src/blas.jl +++ b/stdlib/LinearAlgebra/src/blas.jl @@ -138,7 +138,7 @@ function get_num_threads() if blas === :openblas || blas === :openblas64 return ccall((@blasfunc(openblas_get_num_threads), libblas), Cint, ()) elseif blas == :mkl - return ccall((:MKL_Get_Max_Num_Threads, libblas), Cint, ()) + return ccall((:mkl_get_max_threads, libblas), Cint, ()) elseif Sys.isapple() return Base.parse(Cint, ENV["VECLIB_MAXIMUM_THREADS"]) else diff --git a/stdlib/LinearAlgebra/test/blas.jl b/stdlib/LinearAlgebra/test/blas.jl index e6a4a4d758781..c609ef17f1a97 100644 --- a/stdlib/LinearAlgebra/test/blas.jl +++ b/stdlib/LinearAlgebra/test/blas.jl @@ -558,7 +558,7 @@ end @test default isa Integer @test default > 0 new = rand(1:10) - BLAS.set_num_threads(net) + BLAS.set_num_threads(new) @test BLAS.get_num_threads() == new BLAS.set_num_threads(default) @test BLAS.get_num_threads() == default From 0e6f8fba0da1445ce2defcd4f4dfe3be91221b7e Mon Sep 17 00:00:00 2001 From: Jan Weidner Date: Fri, 19 Jun 2020 15:42:00 +0200 Subject: [PATCH 03/30] fix --- stdlib/LinearAlgebra/test/blas.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stdlib/LinearAlgebra/test/blas.jl b/stdlib/LinearAlgebra/test/blas.jl index c609ef17f1a97..14f5f89c8e923 100644 --- a/stdlib/LinearAlgebra/test/blas.jl +++ b/stdlib/LinearAlgebra/test/blas.jl @@ -557,7 +557,7 @@ end default = BLAS.get_num_threads() @test default isa Integer @test default > 0 - new = rand(1:10) + new=rand(1:Sys.CPU_THREADS) BLAS.set_num_threads(new) @test BLAS.get_num_threads() == new BLAS.set_num_threads(default) From 9f396c2b485bd4bc67744659cf6dfef633f4aacd Mon Sep 17 00:00:00 2001 From: Jan Weidner Date: Fri, 19 Jun 2020 16:12:32 +0200 Subject: [PATCH 04/30] fix --- stdlib/LinearAlgebra/src/blas.jl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/stdlib/LinearAlgebra/src/blas.jl b/stdlib/LinearAlgebra/src/blas.jl index 85d42251b3321..4d2b9b22f4e48 100644 --- a/stdlib/LinearAlgebra/src/blas.jl +++ b/stdlib/LinearAlgebra/src/blas.jl @@ -139,11 +139,11 @@ function get_num_threads() return ccall((@blasfunc(openblas_get_num_threads), libblas), Cint, ()) elseif blas == :mkl return ccall((:mkl_get_max_threads, libblas), Cint, ()) - elseif Sys.isapple() + end + @static if Sys.isapple() return Base.parse(Cint, ENV["VECLIB_MAXIMUM_THREADS"]) - else - error("Unknown BLAS") # better error? return nothing end + error("Unknown BLAS") # better error? return nothing? end const _testmat = [1.0 0.0; 0.0 -1.0] From e84c2581705cbb7037aba2e6cda88bcdacce7b72 Mon Sep 17 00:00:00 2001 From: Jan Weidner Date: Fri, 19 Jun 2020 18:06:43 +0200 Subject: [PATCH 05/30] fix --- stdlib/LinearAlgebra/test/blas.jl | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/stdlib/LinearAlgebra/test/blas.jl b/stdlib/LinearAlgebra/test/blas.jl index 14f5f89c8e923..bc51f812f5ef9 100644 --- a/stdlib/LinearAlgebra/test/blas.jl +++ b/stdlib/LinearAlgebra/test/blas.jl @@ -557,9 +557,8 @@ end default = BLAS.get_num_threads() @test default isa Integer @test default > 0 - new=rand(1:Sys.CPU_THREADS) - BLAS.set_num_threads(new) - @test BLAS.get_num_threads() == new + BLAS.set_num_threads(1) + @test BLAS.get_num_threads() == 1 BLAS.set_num_threads(default) @test BLAS.get_num_threads() == default end From 9a0edcb1bee51ac69f7a0e3df31a3113908a9bfb Mon Sep 17 00:00:00 2001 From: Jan Weidner Date: Fri, 19 Jun 2020 21:53:00 +0200 Subject: [PATCH 06/30] warn if get/set of num_bals_threads fails --- stdlib/LinearAlgebra/src/blas.jl | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/stdlib/LinearAlgebra/src/blas.jl b/stdlib/LinearAlgebra/src/blas.jl index 4d2b9b22f4e48..d4eb988bf98a0 100644 --- a/stdlib/LinearAlgebra/src/blas.jl +++ b/stdlib/LinearAlgebra/src/blas.jl @@ -118,11 +118,11 @@ function set_num_threads(n::Integer) elseif blas === :mkl # MKL may let us set the number of threads in several ways return ccall((:MKL_Set_Num_Threads, libblas), Cvoid, (Cint,), n) - end - - # OSX BLAS looks at an environment variable - @static if Sys.isapple() + elseif Sys.isapple() + # OSX BLAS looks at an environment variable ENV["VECLIB_MAXIMUM_THREADS"] = n + else + @warn "Failed to set number of BLAS threads." end return nothing @@ -139,11 +139,18 @@ function get_num_threads() return ccall((@blasfunc(openblas_get_num_threads), libblas), Cint, ()) elseif blas == :mkl return ccall((:mkl_get_max_threads, libblas), Cint, ()) + elseif Sys.isapple() + key = "VECLIB_MAXIMUM_THREADS" + s = get(ENV, key, "") + nt = Base.tryparse(Cint, s) + if nt === nothing + @warn "Failed to read environment variable $key" + else + return nt + end end - @static if Sys.isapple() - return Base.parse(Cint, ENV["VECLIB_MAXIMUM_THREADS"]) - end - error("Unknown BLAS") # better error? return nothing? + @warn "Could not get number of BLAS threads. Returning Sys.CPU_THREADS instead." + return Sys.CPU_THREADS end const _testmat = [1.0 0.0; 0.0 -1.0] From f6daa7905fda8aea111feea0f7d27448a2fb1f10 Mon Sep 17 00:00:00 2001 From: Jan Weidner Date: Sat, 20 Jun 2020 07:44:38 +0200 Subject: [PATCH 07/30] Update stdlib/LinearAlgebra/src/blas.jl Co-authored-by: Takafumi Arakaki --- stdlib/LinearAlgebra/src/blas.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stdlib/LinearAlgebra/src/blas.jl b/stdlib/LinearAlgebra/src/blas.jl index d4eb988bf98a0..6787933007235 100644 --- a/stdlib/LinearAlgebra/src/blas.jl +++ b/stdlib/LinearAlgebra/src/blas.jl @@ -149,7 +149,7 @@ function get_num_threads() return nt end end - @warn "Could not get number of BLAS threads. Returning Sys.CPU_THREADS instead." + @warn "Could not get number of BLAS threads. Returning Sys.CPU_THREADS instead." maxlog=1 return Sys.CPU_THREADS end From 8b2c8c47a20c942c590d368a63a82403e9ce5b8c Mon Sep 17 00:00:00 2001 From: Jan Weidner Date: Sat, 20 Jun 2020 07:44:50 +0200 Subject: [PATCH 08/30] Update stdlib/LinearAlgebra/src/blas.jl Co-authored-by: Takafumi Arakaki --- stdlib/LinearAlgebra/src/blas.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stdlib/LinearAlgebra/src/blas.jl b/stdlib/LinearAlgebra/src/blas.jl index 6787933007235..b17605f876b50 100644 --- a/stdlib/LinearAlgebra/src/blas.jl +++ b/stdlib/LinearAlgebra/src/blas.jl @@ -144,7 +144,7 @@ function get_num_threads() s = get(ENV, key, "") nt = Base.tryparse(Cint, s) if nt === nothing - @warn "Failed to read environment variable $key" + @warn "Failed to read environment variable $key" maxlog=1 else return nt end From a15f85194c0f27ad0af5900f1570e6f8a8eb94fc Mon Sep 17 00:00:00 2001 From: Jan Weidner Date: Sat, 20 Jun 2020 07:45:07 +0200 Subject: [PATCH 09/30] Update stdlib/LinearAlgebra/src/blas.jl Co-authored-by: Takafumi Arakaki --- stdlib/LinearAlgebra/src/blas.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stdlib/LinearAlgebra/src/blas.jl b/stdlib/LinearAlgebra/src/blas.jl index b17605f876b50..3c921111cf103 100644 --- a/stdlib/LinearAlgebra/src/blas.jl +++ b/stdlib/LinearAlgebra/src/blas.jl @@ -122,7 +122,7 @@ function set_num_threads(n::Integer) # OSX BLAS looks at an environment variable ENV["VECLIB_MAXIMUM_THREADS"] = n else - @warn "Failed to set number of BLAS threads." + @warn "Failed to set number of BLAS threads." maxlog=1 end return nothing From 826d8ff3b08f7be0bf1f4d511d41595e92850f1e Mon Sep 17 00:00:00 2001 From: Jan Weidner Date: Sat, 20 Jun 2020 08:15:19 +0200 Subject: [PATCH 10/30] fix --- stdlib/LinearAlgebra/src/blas.jl | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/stdlib/LinearAlgebra/src/blas.jl b/stdlib/LinearAlgebra/src/blas.jl index 3c921111cf103..2743c5f8ad663 100644 --- a/stdlib/LinearAlgebra/src/blas.jl +++ b/stdlib/LinearAlgebra/src/blas.jl @@ -107,9 +107,14 @@ end openblas_get_config() = strip(unsafe_string(ccall((@blasfunc(openblas_get_config), libblas), Ptr{UInt8}, () ))) """ - set_num_threads(n) + set_num_threads(n::Integer) + set_num_threads(::Nothing) + +Set the number of threads the BLAS library should use equal to `n::Integer`. +If `nothing` is passed to this function, julia tries to figure out the optimial number of threads. +The exact heuristic is an implementation detail. -Set the number of threads the BLAS library should use. +On exotic variants of `BLAS` this function can fail, which is indicated by returning `nothing`. """ function set_num_threads(n::Integer) blas = vendor() @@ -128,10 +133,17 @@ function set_num_threads(n::Integer) return nothing end +function set_num_threads(::Nothing) + n = max(1, Sys.CPU_THREADS ÷ 2) + set_num_threads(n) +end + """ get_num_threads() Get the number of threads the BLAS library is using. + +On exotic variants of `BLAS` this function can fail, which is indicated by returning `nothing`. """ function get_num_threads() blas = LinearAlgebra.BLAS.vendor() @@ -149,8 +161,9 @@ function get_num_threads() return nt end end - @warn "Could not get number of BLAS threads. Returning Sys.CPU_THREADS instead." maxlog=1 - return Sys.CPU_THREADS + ret = nothing + @warn "Could not get number of BLAS threads. Returning $ret instead." maxlog=1 + return ret end const _testmat = [1.0 0.0; 0.0 -1.0] From ce6163635e2d200359cc5f688cd84d473627faf2 Mon Sep 17 00:00:00 2001 From: Jan Weidner Date: Sat, 20 Jun 2020 08:35:18 +0200 Subject: [PATCH 11/30] Update stdlib/LinearAlgebra/src/blas.jl Co-authored-by: Takafumi Arakaki --- stdlib/LinearAlgebra/src/blas.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stdlib/LinearAlgebra/src/blas.jl b/stdlib/LinearAlgebra/src/blas.jl index 2743c5f8ad663..860a33ffee690 100644 --- a/stdlib/LinearAlgebra/src/blas.jl +++ b/stdlib/LinearAlgebra/src/blas.jl @@ -162,7 +162,7 @@ function get_num_threads() end end ret = nothing - @warn "Could not get number of BLAS threads. Returning $ret instead." maxlog=1 + @warn "Could not get number of BLAS threads. Returning `$ret` instead." maxlog=1 return ret end From b38afaa9681f148f8a5691c4e519c2c8fea7374f Mon Sep 17 00:00:00 2001 From: Jan Weidner Date: Sat, 20 Jun 2020 09:14:44 +0200 Subject: [PATCH 12/30] Update stdlib/LinearAlgebra/src/blas.jl Co-authored-by: Takafumi Arakaki --- stdlib/LinearAlgebra/src/blas.jl | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/stdlib/LinearAlgebra/src/blas.jl b/stdlib/LinearAlgebra/src/blas.jl index 860a33ffee690..7b12058d07998 100644 --- a/stdlib/LinearAlgebra/src/blas.jl +++ b/stdlib/LinearAlgebra/src/blas.jl @@ -133,8 +133,14 @@ function set_num_threads(n::Integer) return nothing end +_tryparse_env_cint(key) = tryparse(Cint, get(ENV, key, "")) + function set_num_threads(::Nothing) - n = max(1, Sys.CPU_THREADS ÷ 2) + n = something( + _tryparse_env_cint("OPENBLAS_NUM_THREADS"), + _tryparse_env_cint("OMP_NUM_THREADS"), + max(1, Sys.CPU_THREADS ÷ 2), + ) set_num_threads(n) end From 0ee0efaef576934b1cbac2b20bf38b52c4e73ae4 Mon Sep 17 00:00:00 2001 From: Jan Weidner Date: Sat, 20 Jun 2020 09:16:06 +0200 Subject: [PATCH 13/30] Update stdlib/LinearAlgebra/src/blas.jl Co-authored-by: Takafumi Arakaki --- stdlib/LinearAlgebra/src/blas.jl | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/stdlib/LinearAlgebra/src/blas.jl b/stdlib/LinearAlgebra/src/blas.jl index 7b12058d07998..aa415aeb406fb 100644 --- a/stdlib/LinearAlgebra/src/blas.jl +++ b/stdlib/LinearAlgebra/src/blas.jl @@ -167,9 +167,8 @@ function get_num_threads() return nt end end - ret = nothing - @warn "Could not get number of BLAS threads. Returning `$ret` instead." maxlog=1 - return ret + @warn "Could not get number of BLAS threads. Returning `nothing` instead." maxlog=1 + return nothing end const _testmat = [1.0 0.0; 0.0 -1.0] From 8e4fedd2785011a02d2d82f2d94f5ef36d419def Mon Sep 17 00:00:00 2001 From: Jan Weidner Date: Sat, 20 Jun 2020 09:30:18 +0200 Subject: [PATCH 14/30] fix --- stdlib/LinearAlgebra/src/blas.jl | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/stdlib/LinearAlgebra/src/blas.jl b/stdlib/LinearAlgebra/src/blas.jl index aa415aeb406fb..3310cd5c77290 100644 --- a/stdlib/LinearAlgebra/src/blas.jl +++ b/stdlib/LinearAlgebra/src/blas.jl @@ -114,12 +114,12 @@ Set the number of threads the BLAS library should use equal to `n::Integer`. If `nothing` is passed to this function, julia tries to figure out the optimial number of threads. The exact heuristic is an implementation detail. -On exotic variants of `BLAS` this function can fail, which is indicated by returning `nothing`. +On exotic variants of `BLAS` this function can fail. """ -function set_num_threads(n::Integer) +function set_num_threads(n::Integer)::Nothing blas = vendor() if blas === :openblas || blas == :openblas64 - return ccall((@blasfunc(openblas_set_num_threads), libblas), Cvoid, (Int32,), n) + return ccall((@blasfunc(openblas_set_num_threads), libblas), Cvoid, (Cint,), n) elseif blas === :mkl # MKL may let us set the number of threads in several ways return ccall((:MKL_Set_Num_Threads, libblas), Cvoid, (Cint,), n) @@ -129,7 +129,6 @@ function set_num_threads(n::Integer) else @warn "Failed to set number of BLAS threads." maxlog=1 end - return nothing end @@ -151,16 +150,16 @@ Get the number of threads the BLAS library is using. On exotic variants of `BLAS` this function can fail, which is indicated by returning `nothing`. """ -function get_num_threads() +function get_num_threads()::Union{Int, Nothing} blas = LinearAlgebra.BLAS.vendor() if blas === :openblas || blas === :openblas64 - return ccall((@blasfunc(openblas_get_num_threads), libblas), Cint, ()) + return Int(ccall((@blasfunc(openblas_get_num_threads), libblas), Cint, ())) elseif blas == :mkl - return ccall((:mkl_get_max_threads, libblas), Cint, ()) + return Int(ccall((:mkl_get_max_threads, libblas), Cint, ())) elseif Sys.isapple() key = "VECLIB_MAXIMUM_THREADS" s = get(ENV, key, "") - nt = Base.tryparse(Cint, s) + nt = Base.tryparse(Int, s) if nt === nothing @warn "Failed to read environment variable $key" maxlog=1 else From 33a95d58d1b31844591f51c9357651c30bd4338c Mon Sep 17 00:00:00 2001 From: Jan Weidner Date: Sat, 20 Jun 2020 09:43:13 +0200 Subject: [PATCH 15/30] Update stdlib/LinearAlgebra/src/blas.jl Co-authored-by: Takafumi Arakaki --- stdlib/LinearAlgebra/src/blas.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stdlib/LinearAlgebra/src/blas.jl b/stdlib/LinearAlgebra/src/blas.jl index 3310cd5c77290..68484a94fc324 100644 --- a/stdlib/LinearAlgebra/src/blas.jl +++ b/stdlib/LinearAlgebra/src/blas.jl @@ -132,7 +132,7 @@ function set_num_threads(n::Integer)::Nothing return nothing end -_tryparse_env_cint(key) = tryparse(Cint, get(ENV, key, "")) +_tryparse_env_int(key) = tryparse(Int, get(ENV, key, "")) function set_num_threads(::Nothing) n = something( From 35cf5a65974381387a150a64ede82b833019c8ae Mon Sep 17 00:00:00 2001 From: Jan Weidner Date: Sat, 20 Jun 2020 09:43:24 +0200 Subject: [PATCH 16/30] Update stdlib/LinearAlgebra/src/blas.jl Co-authored-by: Takafumi Arakaki --- stdlib/LinearAlgebra/src/blas.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/stdlib/LinearAlgebra/src/blas.jl b/stdlib/LinearAlgebra/src/blas.jl index 68484a94fc324..3b50a083c4f8f 100644 --- a/stdlib/LinearAlgebra/src/blas.jl +++ b/stdlib/LinearAlgebra/src/blas.jl @@ -136,8 +136,8 @@ _tryparse_env_int(key) = tryparse(Int, get(ENV, key, "")) function set_num_threads(::Nothing) n = something( - _tryparse_env_cint("OPENBLAS_NUM_THREADS"), - _tryparse_env_cint("OMP_NUM_THREADS"), + _tryparse_env_int("OPENBLAS_NUM_THREADS"), + _tryparse_env_int("OMP_NUM_THREADS"), max(1, Sys.CPU_THREADS ÷ 2), ) set_num_threads(n) From bc370b4de4e7d1864758ef9b30c121354f61edb1 Mon Sep 17 00:00:00 2001 From: Jan Weidner Date: Sat, 20 Jun 2020 09:43:38 +0200 Subject: [PATCH 17/30] Update stdlib/LinearAlgebra/src/blas.jl Co-authored-by: Takafumi Arakaki --- stdlib/LinearAlgebra/src/blas.jl | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/stdlib/LinearAlgebra/src/blas.jl b/stdlib/LinearAlgebra/src/blas.jl index 3b50a083c4f8f..ba91cb30f0bdd 100644 --- a/stdlib/LinearAlgebra/src/blas.jl +++ b/stdlib/LinearAlgebra/src/blas.jl @@ -158,8 +158,7 @@ function get_num_threads()::Union{Int, Nothing} return Int(ccall((:mkl_get_max_threads, libblas), Cint, ())) elseif Sys.isapple() key = "VECLIB_MAXIMUM_THREADS" - s = get(ENV, key, "") - nt = Base.tryparse(Int, s) + nt = _tryparse_env_int(key) if nt === nothing @warn "Failed to read environment variable $key" maxlog=1 else From dd455b534d0c2e8dba1cab49eacd30d26a2c3f79 Mon Sep 17 00:00:00 2001 From: Jan Weidner Date: Sat, 20 Jun 2020 15:57:37 +0200 Subject: [PATCH 18/30] Update stdlib/LinearAlgebra/src/blas.jl Co-authored-by: Okon Samuel <39421418+OkonSamuel@users.noreply.github.com> --- stdlib/LinearAlgebra/src/blas.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stdlib/LinearAlgebra/src/blas.jl b/stdlib/LinearAlgebra/src/blas.jl index ba91cb30f0bdd..9185bdcafceb1 100644 --- a/stdlib/LinearAlgebra/src/blas.jl +++ b/stdlib/LinearAlgebra/src/blas.jl @@ -151,7 +151,7 @@ Get the number of threads the BLAS library is using. On exotic variants of `BLAS` this function can fail, which is indicated by returning `nothing`. """ function get_num_threads()::Union{Int, Nothing} - blas = LinearAlgebra.BLAS.vendor() + blas = vendor() if blas === :openblas || blas === :openblas64 return Int(ccall((@blasfunc(openblas_get_num_threads), libblas), Cint, ())) elseif blas == :mkl From abd2084457972504b23a0015f6c0412ff7c585a6 Mon Sep 17 00:00:00 2001 From: Jan Weidner Date: Mon, 22 Jun 2020 12:34:19 +0200 Subject: [PATCH 19/30] fix --- stdlib/LinearAlgebra/src/blas.jl | 36 ++++++++++++++++++++----------- stdlib/LinearAlgebra/test/blas.jl | 8 +++++++ 2 files changed, 32 insertions(+), 12 deletions(-) diff --git a/stdlib/LinearAlgebra/src/blas.jl b/stdlib/LinearAlgebra/src/blas.jl index 9185bdcafceb1..454e1e517ffa0 100644 --- a/stdlib/LinearAlgebra/src/blas.jl +++ b/stdlib/LinearAlgebra/src/blas.jl @@ -106,6 +106,17 @@ end openblas_get_config() = strip(unsafe_string(ccall((@blasfunc(openblas_get_config), libblas), Ptr{UInt8}, () ))) +function guess_vendor() + # like determine_vendor, but guesses blas in some cases + # where determine_vendor returns :unknown + ret = vendor() + if Sys.isapple() && (ret == :unknown ) + ret = :osxblas + end + ret +end + + """ set_num_threads(n::Integer) set_num_threads(::Nothing) @@ -116,17 +127,17 @@ The exact heuristic is an implementation detail. On exotic variants of `BLAS` this function can fail. """ -function set_num_threads(n::Integer)::Nothing - blas = vendor() - if blas === :openblas || blas == :openblas64 +function set_num_threads(n::Integer, _blas=guess_vendor())::Nothing + if _blas === :openblas || _blas == :openblas64 return ccall((@blasfunc(openblas_set_num_threads), libblas), Cvoid, (Cint,), n) - elseif blas === :mkl + elseif _blas === :mkl # MKL may let us set the number of threads in several ways return ccall((:MKL_Set_Num_Threads, libblas), Cvoid, (Cint,), n) - elseif Sys.isapple() + elseif _blas === :osxblas # OSX BLAS looks at an environment variable ENV["VECLIB_MAXIMUM_THREADS"] = n else + @assert _blas === :unknown @warn "Failed to set number of BLAS threads." maxlog=1 end return nothing @@ -134,13 +145,13 @@ end _tryparse_env_int(key) = tryparse(Int, get(ENV, key, "")) -function set_num_threads(::Nothing) +function set_num_threads(::Nothing, _blas=guess_vendor()) n = something( _tryparse_env_int("OPENBLAS_NUM_THREADS"), _tryparse_env_int("OMP_NUM_THREADS"), max(1, Sys.CPU_THREADS ÷ 2), ) - set_num_threads(n) + set_num_threads(n, _blas) end """ @@ -150,13 +161,12 @@ Get the number of threads the BLAS library is using. On exotic variants of `BLAS` this function can fail, which is indicated by returning `nothing`. """ -function get_num_threads()::Union{Int, Nothing} - blas = vendor() - if blas === :openblas || blas === :openblas64 +function get_num_threads(_blas=guess_vendor())::Union{Int, Nothing} + if _blas === :openblas || _blas === :openblas64 return Int(ccall((@blasfunc(openblas_get_num_threads), libblas), Cint, ())) - elseif blas == :mkl + elseif _blas === :mkl return Int(ccall((:mkl_get_max_threads, libblas), Cint, ())) - elseif Sys.isapple() + elseif _blas === :osxblas key = "VECLIB_MAXIMUM_THREADS" nt = _tryparse_env_int(key) if nt === nothing @@ -164,6 +174,8 @@ function get_num_threads()::Union{Int, Nothing} else return nt end + else + @assert _blas === :unknown end @warn "Could not get number of BLAS threads. Returning `nothing` instead." maxlog=1 return nothing diff --git a/stdlib/LinearAlgebra/test/blas.jl b/stdlib/LinearAlgebra/test/blas.jl index bc51f812f5ef9..0899c5af362ff 100644 --- a/stdlib/LinearAlgebra/test/blas.jl +++ b/stdlib/LinearAlgebra/test/blas.jl @@ -561,6 +561,14 @@ end @test BLAS.get_num_threads() == 1 BLAS.set_num_threads(default) @test BLAS.get_num_threads() == default + + if BLAS.guess_vendor() !== :osxblas + # test osxblas which is not covered by CI + BLAS.set_num_threads(1, :osxblas) + @test BLAS.get_num_threads(:osxblas) === 1 + BLAS.set_num_threads(2, :osxblas) + @test BLAS.get_num_threads(:osxblas) === 2 + end end end # module TestBLAS From b8e9055123e27a3a97600009640ae0476ce9293d Mon Sep 17 00:00:00 2001 From: Jan Weidner Date: Mon, 22 Jun 2020 20:59:40 +0200 Subject: [PATCH 20/30] fix --- stdlib/LinearAlgebra/src/blas.jl | 8 ++++---- stdlib/LinearAlgebra/test/blas.jl | 14 +++++++------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/stdlib/LinearAlgebra/src/blas.jl b/stdlib/LinearAlgebra/src/blas.jl index 454e1e517ffa0..ca96069628898 100644 --- a/stdlib/LinearAlgebra/src/blas.jl +++ b/stdlib/LinearAlgebra/src/blas.jl @@ -127,7 +127,7 @@ The exact heuristic is an implementation detail. On exotic variants of `BLAS` this function can fail. """ -function set_num_threads(n::Integer, _blas=guess_vendor())::Nothing +function set_num_threads(n::Integer; _blas=guess_vendor())::Nothing if _blas === :openblas || _blas == :openblas64 return ccall((@blasfunc(openblas_set_num_threads), libblas), Cvoid, (Cint,), n) elseif _blas === :mkl @@ -145,13 +145,13 @@ end _tryparse_env_int(key) = tryparse(Int, get(ENV, key, "")) -function set_num_threads(::Nothing, _blas=guess_vendor()) +function set_num_threads(::Nothing; _blas=guess_vendor()) n = something( _tryparse_env_int("OPENBLAS_NUM_THREADS"), _tryparse_env_int("OMP_NUM_THREADS"), max(1, Sys.CPU_THREADS ÷ 2), ) - set_num_threads(n, _blas) + set_num_threads(n; _blas) end """ @@ -161,7 +161,7 @@ Get the number of threads the BLAS library is using. On exotic variants of `BLAS` this function can fail, which is indicated by returning `nothing`. """ -function get_num_threads(_blas=guess_vendor())::Union{Int, Nothing} +function get_num_threads(;_blas=guess_vendor())::Union{Int, Nothing} if _blas === :openblas || _blas === :openblas64 return Int(ccall((@blasfunc(openblas_get_num_threads), libblas), Cint, ())) elseif _blas === :mkl diff --git a/stdlib/LinearAlgebra/test/blas.jl b/stdlib/LinearAlgebra/test/blas.jl index 0899c5af362ff..26867e0928315 100644 --- a/stdlib/LinearAlgebra/test/blas.jl +++ b/stdlib/LinearAlgebra/test/blas.jl @@ -555,19 +555,19 @@ end @testset "get_set_num_threads" begin default = BLAS.get_num_threads() - @test default isa Integer + @test default isa Int @test default > 0 BLAS.set_num_threads(1) - @test BLAS.get_num_threads() == 1 + @test BLAS.get_num_threads() === 1 BLAS.set_num_threads(default) - @test BLAS.get_num_threads() == default + @test BLAS.get_num_threads() === default if BLAS.guess_vendor() !== :osxblas # test osxblas which is not covered by CI - BLAS.set_num_threads(1, :osxblas) - @test BLAS.get_num_threads(:osxblas) === 1 - BLAS.set_num_threads(2, :osxblas) - @test BLAS.get_num_threads(:osxblas) === 2 + BLAS.set_num_threads(1, _blas=:osxblas) + @test BLAS.get_num_threads(_blas=:osxblas) === 1 + BLAS.set_num_threads(2, _blas=:osxblas) + @test BLAS.get_num_threads(_blas=:osxblas) === 2 end end From 9eabcb6b559bbd86f4c43418a7950789729a4536 Mon Sep 17 00:00:00 2001 From: Jan Weidner Date: Tue, 23 Jun 2020 07:50:06 +0200 Subject: [PATCH 21/30] Update stdlib/LinearAlgebra/src/blas.jl Co-authored-by: Takafumi Arakaki --- stdlib/LinearAlgebra/src/blas.jl | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/stdlib/LinearAlgebra/src/blas.jl b/stdlib/LinearAlgebra/src/blas.jl index ca96069628898..09b1c4b0a0d59 100644 --- a/stdlib/LinearAlgebra/src/blas.jl +++ b/stdlib/LinearAlgebra/src/blas.jl @@ -127,7 +127,9 @@ The exact heuristic is an implementation detail. On exotic variants of `BLAS` this function can fail. """ -function set_num_threads(n::Integer; _blas=guess_vendor())::Nothing +set_num_threads(n)::Nothing = _set_num_threads(n) + +function _set_num_threads(n::Integer; _blas = guess_vendor()) if _blas === :openblas || _blas == :openblas64 return ccall((@blasfunc(openblas_set_num_threads), libblas), Cvoid, (Cint,), n) elseif _blas === :mkl From 920b90bb8f4f0806cefd3b4ed15e61f150b1fccd Mon Sep 17 00:00:00 2001 From: Jan Weidner Date: Tue, 23 Jun 2020 07:50:17 +0200 Subject: [PATCH 22/30] Update stdlib/LinearAlgebra/src/blas.jl Co-authored-by: Takafumi Arakaki --- stdlib/LinearAlgebra/src/blas.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stdlib/LinearAlgebra/src/blas.jl b/stdlib/LinearAlgebra/src/blas.jl index 09b1c4b0a0d59..18bf16e1a5a03 100644 --- a/stdlib/LinearAlgebra/src/blas.jl +++ b/stdlib/LinearAlgebra/src/blas.jl @@ -147,7 +147,7 @@ end _tryparse_env_int(key) = tryparse(Int, get(ENV, key, "")) -function set_num_threads(::Nothing; _blas=guess_vendor()) +function _set_num_threads(::Nothing; _blas = guess_vendor()) n = something( _tryparse_env_int("OPENBLAS_NUM_THREADS"), _tryparse_env_int("OMP_NUM_THREADS"), From b011dc6bfd7a6cea5479de4d87b95fd8e60c6899 Mon Sep 17 00:00:00 2001 From: Jan Weidner Date: Tue, 23 Jun 2020 07:50:33 +0200 Subject: [PATCH 23/30] Update stdlib/LinearAlgebra/src/blas.jl Co-authored-by: Takafumi Arakaki --- stdlib/LinearAlgebra/src/blas.jl | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/stdlib/LinearAlgebra/src/blas.jl b/stdlib/LinearAlgebra/src/blas.jl index 18bf16e1a5a03..95cc55c41d5d7 100644 --- a/stdlib/LinearAlgebra/src/blas.jl +++ b/stdlib/LinearAlgebra/src/blas.jl @@ -163,7 +163,9 @@ Get the number of threads the BLAS library is using. On exotic variants of `BLAS` this function can fail, which is indicated by returning `nothing`. """ -function get_num_threads(;_blas=guess_vendor())::Union{Int, Nothing} +get_num_threads(;_blas=guess_vendor())::Union{Int, Nothing} = _get_num_threads() + +function _get_num_threads(; _blas = guess_vendor())::Union{Int, Nothing} if _blas === :openblas || _blas === :openblas64 return Int(ccall((@blasfunc(openblas_get_num_threads), libblas), Cint, ())) elseif _blas === :mkl From 95ccdf90f8fb004384a2d7f16e327c99851427f2 Mon Sep 17 00:00:00 2001 From: Jan Weidner Date: Tue, 23 Jun 2020 07:50:45 +0200 Subject: [PATCH 24/30] Update stdlib/LinearAlgebra/test/blas.jl Co-authored-by: Takafumi Arakaki --- stdlib/LinearAlgebra/test/blas.jl | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/stdlib/LinearAlgebra/test/blas.jl b/stdlib/LinearAlgebra/test/blas.jl index 26867e0928315..f93dad8f34a6c 100644 --- a/stdlib/LinearAlgebra/test/blas.jl +++ b/stdlib/LinearAlgebra/test/blas.jl @@ -564,10 +564,22 @@ end if BLAS.guess_vendor() !== :osxblas # test osxblas which is not covered by CI - BLAS.set_num_threads(1, _blas=:osxblas) - @test BLAS.get_num_threads(_blas=:osxblas) === 1 - BLAS.set_num_threads(2, _blas=:osxblas) - @test BLAS.get_num_threads(_blas=:osxblas) === 2 + withenv() do + @test_logs (:warn,) match_mode=:any BLAS._set_num_threads(1, _blas=:osxblas) + @test @test_logs( + (:warn,), + (:warn,), + match_mode=:any, + BLAS._get_num_threads(_blas=:osxblas), + ) === 1 + @test_logs (:warn,) match_mode=:any BLAS._set_num_threads(2, _blas=:osxblas) + @test @test_logs( + (:warn,), + (:warn,), + match_mode=:any, + BLAS._get_num_threads(_blas=:osxblas), + ) === 2 + end end end From 72ef30ef7da12ef249e2345ae34a0ef6a5b43c94 Mon Sep 17 00:00:00 2001 From: Jan Weidner Date: Tue, 23 Jun 2020 07:50:57 +0200 Subject: [PATCH 25/30] Update stdlib/LinearAlgebra/src/blas.jl Co-authored-by: Takafumi Arakaki --- stdlib/LinearAlgebra/src/blas.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stdlib/LinearAlgebra/src/blas.jl b/stdlib/LinearAlgebra/src/blas.jl index 95cc55c41d5d7..b338a023d7ba2 100644 --- a/stdlib/LinearAlgebra/src/blas.jl +++ b/stdlib/LinearAlgebra/src/blas.jl @@ -110,7 +110,7 @@ function guess_vendor() # like determine_vendor, but guesses blas in some cases # where determine_vendor returns :unknown ret = vendor() - if Sys.isapple() && (ret == :unknown ) + if Sys.isapple() && (ret == :unknown) ret = :osxblas end ret From 4cf2628104e1e605da894de9e342a9227cf35fc4 Mon Sep 17 00:00:00 2001 From: Jan Weidner Date: Tue, 23 Jun 2020 11:59:30 +0200 Subject: [PATCH 26/30] Update stdlib/LinearAlgebra/test/blas.jl Co-authored-by: Takafumi Arakaki --- stdlib/LinearAlgebra/test/blas.jl | 1 + 1 file changed, 1 insertion(+) diff --git a/stdlib/LinearAlgebra/test/blas.jl b/stdlib/LinearAlgebra/test/blas.jl index f93dad8f34a6c..c8cce0079bb34 100644 --- a/stdlib/LinearAlgebra/test/blas.jl +++ b/stdlib/LinearAlgebra/test/blas.jl @@ -562,6 +562,7 @@ end BLAS.set_num_threads(default) @test BLAS.get_num_threads() === default + @test_logs (:warn,) match_mode=:any BLAS._set_num_threads(1, _blas=:unknown) if BLAS.guess_vendor() !== :osxblas # test osxblas which is not covered by CI withenv() do From bb699315d0460fa53d6b1426c4a1cd5163c709c2 Mon Sep 17 00:00:00 2001 From: Jan Weidner Date: Tue, 23 Jun 2020 12:00:09 +0200 Subject: [PATCH 27/30] Update stdlib/LinearAlgebra/test/blas.jl Co-authored-by: Takafumi Arakaki --- stdlib/LinearAlgebra/test/blas.jl | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/stdlib/LinearAlgebra/test/blas.jl b/stdlib/LinearAlgebra/test/blas.jl index c8cce0079bb34..cefb0625d00d5 100644 --- a/stdlib/LinearAlgebra/test/blas.jl +++ b/stdlib/LinearAlgebra/test/blas.jl @@ -565,21 +565,17 @@ end @test_logs (:warn,) match_mode=:any BLAS._set_num_threads(1, _blas=:unknown) if BLAS.guess_vendor() !== :osxblas # test osxblas which is not covered by CI - withenv() do - @test_logs (:warn,) match_mode=:any BLAS._set_num_threads(1, _blas=:osxblas) + withenv("VECLIB_MAXIMUM_THREADS" => nothing) do @test @test_logs( (:warn,), (:warn,), match_mode=:any, BLAS._get_num_threads(_blas=:osxblas), - ) === 1 - @test_logs (:warn,) match_mode=:any BLAS._set_num_threads(2, _blas=:osxblas) - @test @test_logs( - (:warn,), - (:warn,), - match_mode=:any, - BLAS._get_num_threads(_blas=:osxblas), - ) === 2 + ) === nothing + @test_logs BLAS._set_num_threads(1, _blas=:osxblas) + @test @test_logs(BLAS._get_num_threads(_blas=:osxblas)) === 1 + @test_logs BLAS._set_num_threads(2, _blas=:osxblas) + @test @test_logs(BLAS._get_num_threads(_blas=:osxblas)) === 2 end end end From 06550d6ca62fd65bb394012710f2d00b5b7ff826 Mon Sep 17 00:00:00 2001 From: Jan Weidner Date: Tue, 23 Jun 2020 12:12:23 +0200 Subject: [PATCH 28/30] Update stdlib/LinearAlgebra/src/blas.jl Co-authored-by: Okon Samuel <39421418+OkonSamuel@users.noreply.github.com> --- stdlib/LinearAlgebra/src/blas.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stdlib/LinearAlgebra/src/blas.jl b/stdlib/LinearAlgebra/src/blas.jl index b338a023d7ba2..e0758a26998ea 100644 --- a/stdlib/LinearAlgebra/src/blas.jl +++ b/stdlib/LinearAlgebra/src/blas.jl @@ -153,7 +153,7 @@ function _set_num_threads(::Nothing; _blas = guess_vendor()) _tryparse_env_int("OMP_NUM_THREADS"), max(1, Sys.CPU_THREADS ÷ 2), ) - set_num_threads(n; _blas) + _set_num_threads(n; _blas) end """ From b6aa07629440b59363f750cccc303d51fa179b9b Mon Sep 17 00:00:00 2001 From: Jan Weidner Date: Tue, 23 Jun 2020 13:41:36 +0200 Subject: [PATCH 29/30] improve docstrings --- stdlib/LinearAlgebra/src/blas.jl | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/stdlib/LinearAlgebra/src/blas.jl b/stdlib/LinearAlgebra/src/blas.jl index e0758a26998ea..fca99ceee3f78 100644 --- a/stdlib/LinearAlgebra/src/blas.jl +++ b/stdlib/LinearAlgebra/src/blas.jl @@ -122,10 +122,26 @@ end set_num_threads(::Nothing) Set the number of threads the BLAS library should use equal to `n::Integer`. -If `nothing` is passed to this function, julia tries to figure out the optimial number of threads. -The exact heuristic is an implementation detail. -On exotic variants of `BLAS` this function can fail. +Also accepts `nothing`, in which case julia tries to guess the default number of threads. +Passing `nothing` is discouraged and mainly exists for the following reason: + +On exotic variants of BLAS, `nothing` may be returned by `get_num_threads()`. +Thus on exotic variants of BLAS, the following pattern may fail to set the number of threads: + +```julia +old = get_num_threads() +set_num_threads(1) +@threads for i in 1:10 + # single-threaded BLAS calls +end +set_num_threads(old) +``` +Because `set_num_threads` accepts `nothing`, this code can still run +on exotic variants of BLAS without error. Warnings will be raised instead. + +!!! compat "Julia 1.6" + `set_num_threads(::Nothing)` requires at least Julia 1.6. """ set_num_threads(n)::Nothing = _set_num_threads(n) @@ -162,6 +178,9 @@ end Get the number of threads the BLAS library is using. On exotic variants of `BLAS` this function can fail, which is indicated by returning `nothing`. + +!!! compat "Julia 1.6" + `get_num_threads` requires at least Julia 1.6. """ get_num_threads(;_blas=guess_vendor())::Union{Int, Nothing} = _get_num_threads() From c524c5351def7268c11fa21beb63e3b36192ad81 Mon Sep 17 00:00:00 2001 From: Jan Weidner Date: Tue, 23 Jun 2020 23:14:31 +0200 Subject: [PATCH 30/30] add to NEWS.md --- NEWS.md | 1 + 1 file changed, 1 insertion(+) diff --git a/NEWS.md b/NEWS.md index c9d73854e0f9d..748acc4f87863 100644 --- a/NEWS.md +++ b/NEWS.md @@ -57,6 +57,7 @@ Standard library changes #### LinearAlgebra * New method `LinearAlgebra.issuccess(::CholeskyPivoted)` for checking whether pivoted Cholesky factorization was successful ([#36002]). * `UniformScaling` can now be indexed into using ranges to return dense matrices and vectors ([#24359]). +* New function `LinearAlgebra.BLAS.get_num_threads()` for getting the number of BLAS threads. ([#36360]) #### Markdown