Skip to content

Commit

Permalink
Merge pull request #16600 from JuliaLang/jb/blasutils
Browse files Browse the repository at this point in the history
move BLAS utils into BLAS module
  • Loading branch information
JeffBezanson committed May 27, 2016
2 parents 58d45ea + 5b0be73 commit f6c1a14
Show file tree
Hide file tree
Showing 12 changed files with 102 additions and 103 deletions.
2 changes: 2 additions & 0 deletions base/deprecated.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1264,6 +1264,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

Expand Down
2 changes: 1 addition & 1 deletion base/docs/helpdb/Base.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1521,7 +1521,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
Expand Down
1 change: 0 additions & 1 deletion base/exports.jl
Original file line number Diff line number Diff line change
Expand Up @@ -616,7 +616,6 @@ export
# linear algebra
bkfact!,
bkfact,
blas_set_num_threads,
blkdiag,
chol,
cholfact!,
Expand Down
4 changes: 2 additions & 2 deletions base/interactiveutil.jl
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
4 changes: 2 additions & 2 deletions base/linalg.jl
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
93 changes: 90 additions & 3 deletions base/linalg/blas.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

module BLAS

import Base: copy!, @blasfunc
import Base: copy!
import Base.LinAlg: axpy!, dot

export
Expand Down Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion base/linalg/lapack.jl
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion base/multi.jl
Original file line number Diff line number Diff line change
Expand Up @@ -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"))
Expand Down
88 changes: 0 additions & 88 deletions base/util.jl
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
1 change: 0 additions & 1 deletion contrib/BBEditTextWrangler-julia.plist
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,6 @@
<string>bitunpack</string>
<string>bkfact!</string>
<string>bkfact</string>
<string>blas_set_num_threads</string>
<string>blkdiag</string>
<string>bool</string>
<string>break</string>
Expand Down
4 changes: 2 additions & 2 deletions doc/stdlib/linalg.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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.

Expand Down Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -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")
Expand Down

0 comments on commit f6c1a14

Please sign in to comment.