Use_intel_libm = 1

Is anyone successfully using Intel Math Library (USE_INTEL_LIBM = 1 in Make.user) in a self-compiled Julia 1.0.1?

Pre 1.0 I always used USE_INTEL_LIBM and USE_INTEL_MKL to replace all OpenBLAS by Intel pendants without any issues. However, for 1.0.1 things fail

  math: Error During Test at /projects/sborowsk/julia_build/julia/test/math.jl:841
  Test threw exception
  Expression: ≈(sinh(x), sinh(big(x)), rtol=eps(T))
  ccall: could not find function __ldexp_expf in library libimf

which seems to originate from base/special/hyperbolic.jl where in lines

 _ldexp_exp(x::Float64, i::T) where T = ccall(("__ldexp_exp", libm), Float64, (Float64, T), x, i)
 _ldexp_exp(x::Float32, i::T) where T = ccall(("__ldexp_expf",libm), Float32, (Float32, T), x, i)

libopenlibm specific functions are called which can’t be found in libimf.

If I replace those lines by

_ldexp_exp(x::Float64, i::T) where T = ccall(("ldexp", libm), Float64, (Float64, T), x, i)
_ldexp_exp(x::Float32, i::T) where T = ccall(("ldexpf",libm), Float32, (Float32, T), x, i)

Things work, but the test fails:

Error in testset math:
  Test Failed at /projects/sborowsk/julia_build/julia/test/math.jl:841
    Expression: ≈(sinh(x), sinh(big(x)), rtol=eps(T))
     Evaluated: 44.361416f0 ≈ 1.701399268705924328372129400192948964842537512956506377907196085335400360725516e+38 (rtol=1.1920929f-7)

Any related experiences anyone?

(I will write up a proper bug report if needed.)

3 Likes

Maybe as a motivation for why intel’s math library:

julia> @btime sinh.($(rand(100_000))); # LIBM: libopenlibm
  3.259 ms (2 allocations: 781.33 KiB)
julia> @btime sinh.($(rand(100_000))); # LIBM: libimf
  1.556 ms (2 allocations: 781.33 KiB)

Maybe a little bit irrelevant but I am on v1.0.2 and successfully compile it with intel-libm. In case anyone hits here, if it couldn’t find libimf, you may need to install psxe_runtime:

export LD_LIBRARY_PATH=/opt/intel/psxe_runtime_2019.1.144/linux/compiler/lib/intel64_lin/:$LD_LIBRARY_PATH

And if you using JLD and get complaint about versionCXXABI_1.3.9’ not found`,

export LD_LIBRARY_PATH=/opt/anaconda3/lib/:$LD_LIBRARY_PATH

Or if you don’t want to mess up with the $LD_LIBRARY_PATH, you could edit Make.user similar like me:

USE_SYSTEM_XXX=1
LDFLAGS=-Wl,-rpath,/opt/intel/psxe_runtime/linux/compiler/lib/intel64_lin/
LDFLAGS+=-Wl,-rpath,/opt/gcc8/lib64/
LDFLAGS+=-Wl,-rpath,/opt/intel/compilers_and_libraries_2019.1.144/linux/mkl/lib/intel64_lin/
LDFLAGS+=-L/opt/gcc8/lib64/ -L/opt/intel/psxe_runtime/linux/compiler/lib/intel64_lin/
LDFLAGS+=-L/opt/intel/compilers_and_libraries_2019.1.144/linux/mkl/lib/intel64_lin/

Not irrelevant at all!

I also managed to use Intel’s libm by now. The relevant line mentioned above has been changed between 1.0.0 and 1.0.2 although unrelated to this issue I believe.

I also notice that the performance for those optimized functions like sinh are great!

I encountered the same test error when updating to 1.0 but ignoring it all the time. I think it can be avoidable if and only if linked against openlibm.

These two libraries, __ldexp_exp and __ldexp_expf, do not exist in library libimf, they are openlibm specific, see openlibm/src/k_exp.c and openlibm/src/k_expf.c for details, and they have no equivalents in libimf.so.

The good thing is, in base/special/hyperbolic.jl it only calls these openlibm specific functions when the input of sinh/cosh is between Base.Math.H_LARGE_X(T) [inclusive] and Base.Math.H_OVERFLOW_X(T). That is [88.72283f0, 89.415985f0] for T=Float32 and [709.7822265633563,710.475860073944] for T=Float64.

I guess if you have to work within these two ranges using the corresponding type, you then have to implement something in, for example, myhyperbolic.jl to call directly from libimf to overwrite the ones in defined in base/special/hyperbolic.jl.

1 Like