From 5b0be736877d9d3168c26a6c7f8a6aa5002958dc Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Thu, 26 May 2016 15:51:35 -0400 Subject: [PATCH] move BLAS utils into BLAS module --- base/deprecated.jl | 2 + base/docs/helpdb/Base.jl | 2 +- base/exports.jl | 1 - base/interactiveutil.jl | 4 +- base/linalg.jl | 4 +- base/linalg/blas.jl | 93 +++++++++++++++++++++++++- base/linalg/lapack.jl | 2 +- base/multi.jl | 2 +- base/util.jl | 88 ------------------------ contrib/BBEditTextWrangler-julia.plist | 1 - doc/stdlib/linalg.rst | 4 +- test/runtests.jl | 2 +- 12 files changed, 102 insertions(+), 103 deletions(-) diff --git a/base/deprecated.jl b/base/deprecated.jl index 142f5d6a57c54..afbb2825d35b3 100644 --- a/base/deprecated.jl +++ b/base/deprecated.jl @@ -1254,6 +1254,8 @@ end @deprecate showcompact_lim show +@deprecate blas_set_num_threads BLAS.set_num_threads + # During the 0.5 development cycle, do not add any deprecations below this line # To be deprecated in 0.6 diff --git a/base/docs/helpdb/Base.jl b/base/docs/helpdb/Base.jl index 192885623dbb3..d9b616453dd31 100644 --- a/base/docs/helpdb/Base.jl +++ b/base/docs/helpdb/Base.jl @@ -1536,7 +1536,7 @@ expand [`gemm!`](:func:`Base.LinAlg.BLAS.gemm!`). By default, if no arguments are specified, it multiplies a matrix of size `n x n`, where `n = 2000`. If the underlying BLAS is using multiple threads, higher flop rates are realized. The number of BLAS threads can be set with -`blas_set_num_threads(n)`. +`BLAS.set_num_threads(n)`. If the keyword argument `parallel` is set to `true`, `peakflops` is run in parallel on all the worker processors. The flop rate of the entire parallel computer is returned. When diff --git a/base/exports.jl b/base/exports.jl index e3e54124b3494..7a15a1abc08d6 100644 --- a/base/exports.jl +++ b/base/exports.jl @@ -620,7 +620,6 @@ export # linear algebra bkfact!, bkfact, - blas_set_num_threads, blkdiag, chol, cholfact!, diff --git a/base/interactiveutil.jl b/base/interactiveutil.jl index 53533c078f2c1..7c825a0856f22 100644 --- a/base/interactiveutil.jl +++ b/base/interactiveutil.jl @@ -223,8 +223,8 @@ function versioninfo(io::IO=STDOUT, verbose::Bool=false) Sys.cpu_summary(io) println(io ) end - if Base.libblas_name == "libopenblas" || blas_vendor() == :openblas || blas_vendor() == :openblas64 - openblas_config = openblas_get_config() + if Base.libblas_name == "libopenblas" || BLAS.vendor() == :openblas || BLAS.vendor() == :openblas64 + openblas_config = BLAS.openblas_get_config() println(io, " BLAS: libopenblas (", openblas_config, ")") else println(io, " BLAS: ",libblas_name) diff --git a/base/linalg.jl b/base/linalg.jl index f4f340e5ccdc6..96eb19ceea0de 100644 --- a/base/linalg.jl +++ b/base/linalg.jl @@ -252,8 +252,8 @@ include("linalg/arnoldi.jl") function __init__() try - Base.check_blas() - if Base.blas_vendor() == :mkl + BLAS.check() + if BLAS.vendor() == :mkl ccall((:MKL_Set_Interface_Layer, Base.libblas_name), Void, (Cint,), USE_BLAS64 ? 1 : 0) end catch ex diff --git a/base/linalg/blas.jl b/base/linalg/blas.jl index bf54e2d96964d..4e5f89d96896a 100644 --- a/base/linalg/blas.jl +++ b/base/linalg/blas.jl @@ -2,7 +2,7 @@ module BLAS -import Base: copy!, @blasfunc +import Base: copy! import Base.LinAlg: axpy!, dot export @@ -59,12 +59,99 @@ const liblapack = Base.liblapack_name import ..LinAlg: BlasReal, BlasComplex, BlasFloat, BlasInt, DimensionMismatch, checksquare, axpy! +# utility routines +function vendor() + try + cglobal((:openblas_set_num_threads, Base.libblas_name), Void) + return :openblas + end + try + cglobal((:openblas_set_num_threads64_, Base.libblas_name), Void) + return :openblas64 + end + try + cglobal((:MKL_Set_Num_Threads, Base.libblas_name), Void) + return :mkl + end + return :unknown +end + +if vendor() == :openblas64 + macro blasfunc(x) + return Expr(:quote, Symbol(x, "64_")) + end + openblas_get_config() = strip(String( ccall((:openblas_get_config64_, Base.libblas_name), Ptr{UInt8}, () ))) +else + macro blasfunc(x) + return Expr(:quote, x) + end + openblas_get_config() = strip(String( ccall((:openblas_get_config, Base.libblas_name), Ptr{UInt8}, () ))) +end + """ - blas_set_num_threads(n) + set_num_threads(n) Set the number of threads the BLAS library should use. """ -blas_set_num_threads +function set_num_threads(n::Integer) + blas = vendor() + if blas == :openblas + return ccall((:openblas_set_num_threads, Base.libblas_name), Void, (Int32,), n) + elseif blas == :openblas64 + return ccall((:openblas_set_num_threads64_, Base.libblas_name), Void, (Int32,), n) + elseif blas == :mkl + # MKL may let us set the number of threads in several ways + return ccall((:MKL_Set_Num_Threads, Base.libblas_name), Void, (Cint,), n) + end + + # OSX BLAS looks at an environment variable + @static if is_apple() + ENV["VECLIB_MAXIMUM_THREADS"] = n + end + + return nothing +end + +function check() + blas = vendor() + if blas == :openblas || blas == :openblas64 + openblas_config = openblas_get_config() + openblas64 = ismatch(r".*USE64BITINT.*", openblas_config) + if Base.USE_BLAS64 != openblas64 + if !openblas64 + println("ERROR: OpenBLAS was not built with 64bit integer support.") + println("You're seeing this error because Julia was built with USE_BLAS64=1") + println("Please rebuild Julia with USE_BLAS64=0") + else + println("ERROR: Julia was not built with support for OpenBLAS with 64bit integer support") + println("You're seeing this error because Julia was built with USE_BLAS64=0") + println("Please rebuild Julia with USE_BLAS64=1") + end + println("Quitting.") + quit() + end + elseif blas == :mkl + if Base.USE_BLAS64 + ENV["MKL_INTERFACE_LAYER"] = "ILP64" + end + end + + # + # Check if BlasInt is the expected bitsize, by triggering an error + # + (_, info) = LinAlg.LAPACK.potrf!('U', [1.0 0.0; 0.0 -1.0]) + if info != 2 # mangled info code + if info == 2^33 + error("""BLAS and LAPACK are compiled with 32-bit integer support, but Julia expects 64-bit integers. Please build Julia with USE_BLAS64=0.""") + elseif info == 0 + error("""BLAS and LAPACK are compiled with 64-bit integer support but Julia expects 32-bit integers. Please build Julia with USE_BLAS64=1.""") + else + error("""The LAPACK library produced an undefined error code. Please verify the installation of BLAS and LAPACK.""") + end + end + +end + # Level 1 ## copy diff --git a/base/linalg/lapack.jl b/base/linalg/lapack.jl index 8fb7b856d3d3b..7a40910e07f73 100644 --- a/base/linalg/lapack.jl +++ b/base/linalg/lapack.jl @@ -5,7 +5,7 @@ module LAPACK const liblapack = Base.liblapack_name -import Base.@blasfunc +import ..LinAlg.BLAS.@blasfunc import ..LinAlg: BlasFloat, Char, BlasInt, LAPACKException, DimensionMismatch, SingularException, PosDefException, chkstride1, checksquare diff --git a/base/multi.jl b/base/multi.jl index 3cb3f5d8079bf..6c62cb4fecc35 100644 --- a/base/multi.jl +++ b/base/multi.jl @@ -1144,7 +1144,7 @@ function handle_msg(msg::JoinCompleteMsg, r_stream, w_stream, version) end function disable_threaded_libs() - blas_set_num_threads(1) + BLAS.set_num_threads(1) end worker_timeout() = parse(Float64, get(ENV, "JULIA_WORKER_TIMEOUT", "60.0")) diff --git a/base/util.jl b/base/util.jl index 11443bc45b66f..e4578c3e22ca2 100644 --- a/base/util.jl +++ b/base/util.jl @@ -214,94 +214,6 @@ macro timed(ex) end end -# BLAS utility routines -function blas_vendor() - try - cglobal((:openblas_set_num_threads, Base.libblas_name), Void) - return :openblas - end - try - cglobal((:openblas_set_num_threads64_, Base.libblas_name), Void) - return :openblas64 - end - try - cglobal((:MKL_Set_Num_Threads, Base.libblas_name), Void) - return :mkl - end - return :unknown -end - -if blas_vendor() == :openblas64 - macro blasfunc(x) - return Expr(:quote, Symbol(x, "64_")) - end - openblas_get_config() = strip(String( ccall((:openblas_get_config64_, Base.libblas_name), Ptr{UInt8}, () ))) -else - macro blasfunc(x) - return Expr(:quote, x) - end - openblas_get_config() = strip(String( ccall((:openblas_get_config, Base.libblas_name), Ptr{UInt8}, () ))) -end - -function blas_set_num_threads(n::Integer) - blas = blas_vendor() - if blas == :openblas - return ccall((:openblas_set_num_threads, Base.libblas_name), Void, (Int32,), n) - elseif blas == :openblas64 - return ccall((:openblas_set_num_threads64_, Base.libblas_name), Void, (Int32,), n) - elseif blas == :mkl - # MKL may let us set the number of threads in several ways - return ccall((:MKL_Set_Num_Threads, Base.libblas_name), Void, (Cint,), n) - end - - # OSX BLAS looks at an environment variable - @static if is_apple() - ENV["VECLIB_MAXIMUM_THREADS"] = n - end - - return nothing -end - -function check_blas() - blas = blas_vendor() - if blas == :openblas || blas == :openblas64 - openblas_config = openblas_get_config() - openblas64 = ismatch(r".*USE64BITINT.*", openblas_config) - if Base.USE_BLAS64 != openblas64 - if !openblas64 - println("ERROR: OpenBLAS was not built with 64bit integer support.") - println("You're seeing this error because Julia was built with USE_BLAS64=1") - println("Please rebuild Julia with USE_BLAS64=0") - else - println("ERROR: Julia was not built with support for OpenBLAS with 64bit integer support") - println("You're seeing this error because Julia was built with USE_BLAS64=0") - println("Please rebuild Julia with USE_BLAS64=1") - end - println("Quitting.") - quit() - end - elseif blas == :mkl - if Base.USE_BLAS64 - ENV["MKL_INTERFACE_LAYER"] = "ILP64" - end - end - - # - # Check if BlasInt is the expected bitsize, by triggering an error - # - (_, info) = LinAlg.LAPACK.potrf!('U', [1.0 0.0; 0.0 -1.0]) - if info != 2 # mangled info code - if info == 2^33 - error("""BLAS and LAPACK are compiled with 32-bit integer support, but Julia expects 64-bit integers. Please build Julia with USE_BLAS64=0.""") - elseif info == 0 - error("""BLAS and LAPACK are compiled with 64-bit integer support but Julia expects 32-bit integers. Please build Julia with USE_BLAS64=1.""") - else - error("""The LAPACK library produced an undefined error code. Please verify the installation of BLAS and LAPACK.""") - end - end - -end - function fftw_vendor() if Base.libfftw_name == "libmkl_rt" return :mkl diff --git a/contrib/BBEditTextWrangler-julia.plist b/contrib/BBEditTextWrangler-julia.plist index fcb01a678c577..df7c76524468e 100644 --- a/contrib/BBEditTextWrangler-julia.plist +++ b/contrib/BBEditTextWrangler-julia.plist @@ -216,7 +216,6 @@ bitunpack bkfact! bkfact - blas_set_num_threads blkdiag bool break diff --git a/doc/stdlib/linalg.rst b/doc/stdlib/linalg.rst index a5ce3d49d3f8d..e79e98e2c6e5f 100644 --- a/doc/stdlib/linalg.rst +++ b/doc/stdlib/linalg.rst @@ -1307,7 +1307,7 @@ Linear algebra functions in Julia are largely implemented by calling functions f .. Docstring generated from Julia source - ``peakflops`` computes the peak flop rate of the computer by using double precision :func:`Base.LinAlg.BLAS.gemm!`\ . By default, if no arguments are specified, it multiplies a matrix of size ``n x n``\ , where ``n = 2000``\ . If the underlying BLAS is using multiple threads, higher flop rates are realized. The number of BLAS threads can be set with ``blas_set_num_threads(n)``\ . + ``peakflops`` computes the peak flop rate of the computer by using double precision :func:`Base.LinAlg.BLAS.gemm!`\ . By default, if no arguments are specified, it multiplies a matrix of size ``n x n``\ , where ``n = 2000``\ . If the underlying BLAS is using multiple threads, higher flop rates are realized. The number of BLAS threads can be set with ``BLAS.set_num_threads(n)``\ . If the keyword argument ``parallel`` is set to ``true``\ , ``peakflops`` is run in parallel on all the worker processors. The flop rate of the entire parallel computer is returned. When running in parallel, only 1 BLAS thread is used. The argument ``n`` still refers to the size of the problem that is solved on each processor. @@ -1579,7 +1579,7 @@ Usually a function has 4 methods defined, one each for ``Float64``, Returns the solution to ``A*x = b`` or one of the other two variants determined by ``tA`` (transpose ``A``\ ) and ``ul`` (triangle of ``A`` is used.) ``dA`` indicates if ``A`` is unit-triangular (the diagonal is assumed to be all ones). -.. function:: blas_set_num_threads(n) +.. function:: set_num_threads(n) .. Docstring generated from Julia source diff --git a/test/runtests.jl b/test/runtests.jl index f784a08e08a83..05bcf183941fc 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -15,7 +15,7 @@ cd(dirname(@__FILE__)) do if net_on n = min(8, Sys.CPU_CORES, length(tests)) n > 1 && addprocs(n; exeflags=`--check-bounds=yes --depwarn=error`) - blas_set_num_threads(1) + BLAS.set_num_threads(1) end @everywhere include("testdefs.jl")