1
# - Find INTEL MKL library
3
# This module sets the following variables:
4
# MKL_FOUND - set to true if a library implementing the CBLAS interface is found
5
# MKL_VERSION - best guess of the found mkl version
6
# MKL_INCLUDE_DIR - path to include dir.
7
# MKL_LIBRARIES - list of libraries for base mkl
8
# MKL_OPENMP_TYPE - OpenMP flavor that the found mkl uses: GNU or Intel
9
# MKL_OPENMP_LIBRARY - path to the OpenMP library the found mkl uses
10
# MKL_LAPACK_LIBRARIES - list of libraries to add for lapack
11
# MKL_SCALAPACK_LIBRARIES - list of libraries to add for scalapack
12
# MKL_SOLVER_LIBRARIES - list of libraries to add for the solvers
13
# MKL_CDFT_LIBRARIES - list of libraries to add for the solvers
15
# Do nothing if MKL_FOUND was set before!
22
SET(MKL_OPENMP_LIBRARY)
23
SET(MKL_LAPACK_LIBRARIES)
24
SET(MKL_SCALAPACK_LIBRARIES)
25
SET(MKL_SOLVER_LIBRARIES)
26
SET(MKL_CDFT_LIBRARIES)
30
INCLUDE(CheckFunctionExists)
32
# Set default value of INTEL_COMPILER_DIR and INTEL_MKL_DIR
34
IF(DEFINED ENV{MKLProductDir})
35
SET(DEFAULT_INTEL_COMPILER_DIR $ENV{MKLProductDir})
37
SET(DEFAULT_INTEL_COMPILER_DIR
38
"C:/Program Files (x86)/IntelSWTools/compilers_and_libraries/windows")
40
SET(DEFAULT_INTEL_MKL_DIR "${DEFAULT_INTEL_COMPILER_DIR}/mkl")
41
if (EXISTS "${DEFAULT_INTEL_COMPILER_DIR}/mkl/latest")
42
SET(DEFAULT_INTEL_MKL_DIR "${DEFAULT_INTEL_COMPILER_DIR}/mkl/latest")
45
SET(DEFAULT_INTEL_COMPILER_DIR "/opt/intel")
46
SET(DEFAULT_INTEL_MKL_DIR "/opt/intel/mkl")
47
SET(DEFAULT_INTEL_ONEAPI_DIR "/opt/intel/oneapi")
48
if (EXISTS "${DEFAULT_INTEL_ONEAPI_DIR}")
49
SET(DEFAULT_INTEL_COMPILER_DIR "${DEFAULT_INTEL_ONEAPI_DIR}")
50
if (EXISTS "${DEFAULT_INTEL_ONEAPI_DIR}/compiler/latest")
51
SET(DEFAULT_INTEL_COMPILER_DIR "${DEFAULT_INTEL_ONEAPI_DIR}/compiler/latest")
53
if (EXISTS "${DEFAULT_INTEL_ONEAPI_DIR}/mkl/latest")
54
SET(DEFAULT_INTEL_MKL_DIR "${DEFAULT_INTEL_ONEAPI_DIR}/mkl/latest")
60
SET(INTEL_COMPILER_DIR "${DEFAULT_INTEL_COMPILER_DIR}" CACHE STRING
61
"Root directory of the Intel Compiler Suite (contains ipp, mkl, etc.)")
62
SET(INTEL_MKL_DIR "${DEFAULT_INTEL_MKL_DIR}" CACHE STRING
63
"Root directory of the Intel MKL (standalone)")
64
SET(INTEL_OMP_DIR "${DEFAULT_INTEL_MKL_DIR}" CACHE STRING
65
"Root directory of the Intel OpenMP (standalone)")
66
SET(MKL_THREADING "OMP" CACHE STRING "MKL flavor: SEQ, TBB or OMP (default)")
68
IF (NOT "${MKL_THREADING}" STREQUAL "SEQ" AND
69
NOT "${MKL_THREADING}" STREQUAL "TBB" AND
70
NOT "${MKL_THREADING}" STREQUAL "OMP")
71
MESSAGE(FATAL_ERROR "Invalid MKL_THREADING (${MKL_THREADING}), should be one of: SEQ, TBB, OMP")
74
IF ("${MKL_THREADING}" STREQUAL "TBB" AND NOT USE_TBB)
75
MESSAGE(FATAL_ERROR "MKL_THREADING is TBB but USE_TBB is turned off")
78
MESSAGE(STATUS "MKL_THREADING = ${MKL_THREADING}")
81
CHECK_TYPE_SIZE("void*" SIZE_OF_VOIDP)
82
IF ("${SIZE_OF_VOIDP}" EQUAL 8)
83
SET(mklvers "intel64")
84
SET(iccvers "intel64")
86
ELSE ("${SIZE_OF_VOIDP}" EQUAL 8)
90
ENDIF ("${SIZE_OF_VOIDP}" EQUAL 8)
91
IF(CMAKE_COMPILER_IS_GNUCC)
92
IF ("${MKL_THREADING}" STREQUAL "TBB")
93
SET(mklthreads "mkl_tbb_thread")
96
SET(mklthreads "mkl_gnu_thread" "mkl_intel_thread")
97
SET(mklrtls "gomp" "iomp5")
99
SET(mklifaces "intel" "gf")
100
ELSE(CMAKE_COMPILER_IS_GNUCC)
101
IF ("${MKL_THREADING}" STREQUAL "TBB")
102
SET(mklthreads "mkl_tbb_thread")
105
SET(mklthreads "mkl_intel_thread")
106
SET(mklrtls "iomp5" "guide")
108
SET(mklifaces "intel")
109
ENDIF (CMAKE_COMPILER_IS_GNUCC)
111
# Kernel libraries dynamically loaded
112
SET(mklkerlibs "mc" "mc3" "nc" "p4n" "p4m" "p4m3" "p4p" "def")
116
SET(saved_CMAKE_LIBRARY_PATH ${CMAKE_LIBRARY_PATH})
117
SET(saved_CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH})
118
IF (EXISTS ${INTEL_COMPILER_DIR})
119
# TODO: diagnostic if dir does not exist
120
SET(CMAKE_LIBRARY_PATH ${CMAKE_LIBRARY_PATH}
121
"${INTEL_COMPILER_DIR}/lib/${iccvers}")
123
SET(CMAKE_LIBRARY_PATH ${CMAKE_LIBRARY_PATH}
124
"${INTEL_COMPILER_DIR}/compiler/lib/${iccvers}")
127
SET(CMAKE_LIBRARY_PATH ${CMAKE_LIBRARY_PATH}
128
"${INTEL_COMPILER_DIR}/lib")
130
IF (NOT EXISTS ${INTEL_MKL_DIR})
131
SET(INTEL_MKL_DIR "${INTEL_COMPILER_DIR}/mkl")
134
IF (EXISTS ${INTEL_MKL_DIR})
135
# TODO: diagnostic if dir does not exist
136
SET(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH}
137
"${INTEL_MKL_DIR}/include")
138
SET(CMAKE_LIBRARY_PATH ${CMAKE_LIBRARY_PATH}
139
"${INTEL_MKL_DIR}/lib/${mklvers}")
141
SET(CMAKE_LIBRARY_PATH ${CMAKE_LIBRARY_PATH}
142
"${INTEL_MKL_DIR}/lib/${iccvers}")
143
IF ("${SIZE_OF_VOIDP}" EQUAL 8)
144
SET(CMAKE_LIBRARY_PATH ${CMAKE_LIBRARY_PATH}
145
"${INTEL_MKL_DIR}/win-x64")
149
SET(CMAKE_LIBRARY_PATH ${CMAKE_LIBRARY_PATH}
150
"${INTEL_MKL_DIR}/lib")
154
IF (EXISTS ${INTEL_OMP_DIR})
155
# TODO: diagnostic if dir does not exist
156
SET(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH}
157
"${INTEL_OMP_DIR}/include")
158
SET(CMAKE_LIBRARY_PATH ${CMAKE_LIBRARY_PATH}
159
"${INTEL_OMP_DIR}/lib/${mklvers}")
161
SET(CMAKE_LIBRARY_PATH ${CMAKE_LIBRARY_PATH}
162
"${INTEL_OMP_DIR}/lib/${iccvers}")
163
IF ("${SIZE_OF_VOIDP}" EQUAL 8)
164
SET(CMAKE_LIBRARY_PATH ${CMAKE_LIBRARY_PATH}
165
"${INTEL_OMP_DIR}/win-x64")
169
SET(CMAKE_LIBRARY_PATH ${CMAKE_LIBRARY_PATH}
170
"${INTEL_OMP_DIR}/lib" "${INTEL_COMPILER_DIR}/mac/compiler/lib")
174
MACRO(GET_MKL_LIB_NAMES LIBRARIES INTERFACE MKL64)
175
cmake_parse_arguments("" "" "THREAD" "" ${ARGN})
176
SET(${LIBRARIES} mkl_${INTERFACE}${MKL64} mkl_core)
178
LIST(INSERT ${LIBRARIES} 1 ${_THREAD})
179
IF(UNIX AND ${USE_STATIC_MKL})
180
# The thread library defines symbols required by the other MKL libraries so also add it last
181
LIST(APPEND ${LIBRARIES} ${_THREAD})
184
IF(${USE_STATIC_MKL})
186
list(TRANSFORM ${LIBRARIES} PREPEND "lib")
187
list(TRANSFORM ${LIBRARIES} APPEND ".a")
189
message(WARNING "Ignoring USE_STATIC_MKL")
194
# Try linking multiple libs
195
MACRO(CHECK_ALL_LIBRARIES LIBRARIES OPENMP_TYPE OPENMP_LIBRARY _name _list _flags)
196
# This macro checks for the existence of the combination of libraries given by _list.
197
# If the combination is found, this macro checks whether we can link against that library
198
# combination using the name of a routine given by _name using the linker
199
# flags given by _flags. If the combination of libraries is found and passes
200
# the link test, LIBRARIES is set to the list of complete library paths that
201
# have been found. Otherwise, LIBRARIES is set to FALSE.
202
# N.B. _prefix is the prefix applied to the names of all cached variables that
203
# are generated internally and marked advanced by this macro.
204
SET(_prefix "${LIBRARIES}")
206
SET(_libraries_work TRUE)
209
SET(${OPENMP_LIBRARY})
214
IF (NOT MKL_FIND_QUIETLY)
216
foreach(_elem ${_list})
218
set(_str_list "${_str_list} - ${_elem}")
220
set(_str_list "${_elem}")
223
message(STATUS "Checking for [${_str_list}]")
225
SET(_found_tbb FALSE)
226
FOREACH(_library ${_list})
227
SET(_combined_name ${_combined_name}_${_library})
228
UNSET(${_prefix}_${_library}_LIBRARY)
230
IF(${_library} MATCHES "omp")
232
MESSAGE(FATAL_ERROR "More than one OpenMP libraries appear in the MKL test: ${_list}")
233
ELSEIF(${_library} MATCHES "gomp")
234
SET(_openmp_type "GNU")
235
# Use FindOpenMP to find gomp
236
FIND_PACKAGE(OpenMP QUIET)
238
# Test that none of the found library names contains "iomp" (Intel
239
# OpenMP). This doesn't necessarily mean that we have gomp... but it
240
# is probably good enough since on gcc we should already have
241
# OpenMP_CXX_FLAGS="-fopenmp" and OpenMP_CXX_LIB_NAMES="".
242
SET(_found_gomp true)
243
FOREACH(_lib_name ${OpenMP_CXX_LIB_NAMES})
244
IF (_found_gomp AND "${_lib_name}" MATCHES "iomp")
245
SET(_found_gomp false)
249
SET(${_prefix}_${_library}_LIBRARY ${OpenMP_CXX_FLAGS})
250
SET(_openmp_library "${${_prefix}_${_library}_LIBRARY}")
253
ELSEIF(${_library} MATCHES "iomp")
254
SET(_openmp_type "Intel")
255
FIND_LIBRARY(${_prefix}_${_library}_LIBRARY NAMES ${_library})
256
SET(_openmp_library "${${_prefix}_${_library}_LIBRARY}")
258
MESSAGE(FATAL_ERROR "Unknown OpenMP flavor: ${_library}")
260
ELSEIF(${_library} STREQUAL "tbb")
261
# Separately handling compiled TBB
265
SET(lib_names ${_library}_dll)
267
SET(lib_names ${_library})
269
FIND_LIBRARY(${_prefix}_${_library}_LIBRARY NAMES ${lib_names})
271
MARK_AS_ADVANCED(${_prefix}_${_library}_LIBRARY)
272
IF(NOT (${_library} STREQUAL "tbb"))
273
SET(${LIBRARIES} ${${LIBRARIES}} ${${_prefix}_${_library}_LIBRARY})
274
SET(_libraries_work ${${_prefix}_${_library}_LIBRARY})
275
IF (NOT MKL_FIND_QUIETLY)
276
IF(${_prefix}_${_library}_LIBRARY)
277
MESSAGE(STATUS " Library ${_library}: ${${_prefix}_${_library}_LIBRARY}")
278
ELSE(${_prefix}_${_library}_LIBRARY)
279
MESSAGE(STATUS " Library ${_library}: not found")
280
ENDIF(${_prefix}_${_library}_LIBRARY)
283
ENDIF(_libraries_work)
284
ENDFOREACH(_library ${_list})
285
# Test this combination of libraries.
288
SET(CMAKE_REQUIRED_LIBRARIES ${_flags} ${${LIBRARIES}})
289
SET(CMAKE_REQUIRED_LIBRARIES "${CMAKE_REQUIRED_LIBRARIES};${CMAKE_REQUIRED_LIBRARIES}")
290
CHECK_FUNCTION_EXISTS(${_name} ${_prefix}${_combined_name}_WORKS)
291
SET(CMAKE_REQUIRED_LIBRARIES)
292
MARK_AS_ADVANCED(${_prefix}${_combined_name}_WORKS)
293
SET(_libraries_work ${${_prefix}${_combined_name}_WORKS})
295
ENDIF(_libraries_work)
298
SET(${OPENMP_TYPE} ${_openmp_type})
299
MARK_AS_ADVANCED(${OPENMP_TYPE})
300
SET(${OPENMP_LIBRARY} ${_openmp_library})
301
MARK_AS_ADVANCED(${OPENMP_LIBRARY})
302
ELSE (_libraries_work)
304
MARK_AS_ADVANCED(${LIBRARIES})
305
ENDIF(_libraries_work)
306
ENDMACRO(CHECK_ALL_LIBRARIES)
313
SET(mkl_pthread "pthread")
316
IF(UNIX AND NOT APPLE)
317
SET(mkl_dl "${CMAKE_DL_LIBS}")
318
ELSE(UNIX AND NOT APPLE)
320
ENDIF(UNIX AND NOT APPLE)
322
# Check for version 10/11
323
IF (NOT MKL_LIBRARIES)
324
SET(MKL_VERSION 1011)
325
ENDIF (NOT MKL_LIBRARIES)
327
# First: search for parallelized ones with intel thread lib
328
IF (NOT "${MKL_THREADING}" STREQUAL "SEQ")
329
FOREACH(mklrtl ${mklrtls} "")
330
FOREACH(mkliface ${mklifaces})
331
FOREACH(mkl64 ${mkl64s} "")
332
FOREACH(mklthread ${mklthreads})
333
IF (NOT MKL_LIBRARIES)
334
GET_MKL_LIB_NAMES(mkl_lib_names "${mkliface}" "${mkl64}" THREAD "${mklthread}")
335
CHECK_ALL_LIBRARIES(MKL_LIBRARIES MKL_OPENMP_TYPE MKL_OPENMP_LIBRARY cblas_sgemm
336
"${mkl_lib_names};${mklrtl};${mkl_pthread};${mkl_m};${mkl_dl}" "")
337
ENDIF (NOT MKL_LIBRARIES)
338
ENDFOREACH(mklthread)
342
ENDIF (NOT "${MKL_THREADING}" STREQUAL "SEQ")
344
# Second: search for sequential ones
345
FOREACH(mkliface ${mklifaces})
346
FOREACH(mkl64 ${mkl64s} "")
347
IF (NOT MKL_LIBRARIES)
348
GET_MKL_LIB_NAMES(mkl_lib_names "${mkliface}" "${mkl64}" THREAD "mkl_sequential")
349
CHECK_ALL_LIBRARIES(MKL_LIBRARIES MKL_OPENMP_TYPE MKL_OPENMP_LIBRARY cblas_sgemm
350
"${mkl_lib_names};${mkl_m};${mkl_dl}" "")
352
SET(mklseq "_sequential")
353
ENDIF (MKL_LIBRARIES)
354
ENDIF (NOT MKL_LIBRARIES)
358
# First: search for parallelized ones with native pthread lib
359
FOREACH(mklrtl ${mklrtls} "")
360
FOREACH(mkliface ${mklifaces})
361
FOREACH(mkl64 ${mkl64s} "")
362
IF (NOT MKL_LIBRARIES)
363
GET_MKL_LIB_NAMES(mkl_lib_names "${mkliface}" "${mkl64}" THREAD "${mklthread}")
364
CHECK_ALL_LIBRARIES(MKL_LIBRARIES MKL_OPENMP_TYPE MKL_OPENMP_LIBRARY cblas_sgemm
365
"${mkl_lib_names};${mklrtl};pthread;${mkl_m};${mkl_dl}" "")
366
ENDIF (NOT MKL_LIBRARIES)
372
SET(CMAKE_REQUIRED_LIBRARIES ${MKL_LIBRARIES})
373
check_function_exists("cblas_gemm_bf16bf16f32" MKL_HAS_SBGEMM)
374
check_function_exists("cblas_gemm_f16f16f32" MKL_HAS_SHGEMM)
375
set(CMAKE_REQUIRED_LIBRARIES)
377
add_compile_options(-DMKL_HAS_SBGEMM)
378
ENDIF(MKL_HAS_SBGEMM)
380
add_compile_options(-DMKL_HAS_SHGEMM)
381
ENDIF(MKL_HAS_SHGEMM)
384
# Check for older versions
385
IF (NOT MKL_LIBRARIES)
388
message(WARNING "Ignoring USE_STATIC_MKL")
390
CHECK_ALL_LIBRARIES(MKL_LIBRARIES MKL_OPENMP_TYPE MKL_OPENMP_LIBRARY cblas_sgemm
391
"mkl;guide;pthread;m" "")
392
ENDIF (NOT MKL_LIBRARIES)
396
FIND_PATH(MKL_INCLUDE_DIR NAMES "mkl_cblas.h" PATHS "/usr/include/mkl")
397
MARK_AS_ADVANCED(MKL_INCLUDE_DIR)
402
FOREACH(mkl64 ${mkl64s} "_core" "")
403
FOREACH(mkls ${mklseq} "")
404
IF (NOT MKL_LAPACK_LIBRARIES)
405
FIND_LIBRARY(MKL_LAPACK_LIBRARIES NAMES "mkl_lapack${mkl64}${mkls}")
406
MARK_AS_ADVANCED(MKL_LAPACK_LIBRARIES)
407
ENDIF (NOT MKL_LAPACK_LIBRARIES)
408
IF (NOT MKL_LAPACK_LIBRARIES)
409
FIND_LIBRARY(MKL_LAPACK_LIBRARIES NAMES "mkl_lapack95${mkl64}${mkls}")
410
MARK_AS_ADVANCED(MKL_LAPACK_LIBRARIES)
411
ENDIF (NOT MKL_LAPACK_LIBRARIES)
412
IF (NOT MKL_SCALAPACK_LIBRARIES)
413
FIND_LIBRARY(MKL_SCALAPACK_LIBRARIES NAMES "mkl_scalapack${mkl64}${mkls}")
414
MARK_AS_ADVANCED(MKL_SCALAPACK_LIBRARIES)
415
ENDIF (NOT MKL_SCALAPACK_LIBRARIES)
416
IF (NOT MKL_SOLVER_LIBRARIES)
417
FIND_LIBRARY(MKL_SOLVER_LIBRARIES NAMES "mkl_solver${mkl64}${mkls}")
418
MARK_AS_ADVANCED(MKL_SOLVER_LIBRARIES)
419
ENDIF (NOT MKL_SOLVER_LIBRARIES)
420
IF (NOT MKL_CDFT_LIBRARIES)
421
FIND_LIBRARY(MKL_CDFT_LIBRARIES NAMES "mkl_cdft${mkl64}${mkls}")
422
MARK_AS_ADVANCED(MKL_CDFT_LIBRARIES)
423
ENDIF (NOT MKL_CDFT_LIBRARIES)
429
SET(CMAKE_LIBRARY_PATH ${saved_CMAKE_LIBRARY_PATH})
430
SET(CMAKE_INCLUDE_PATH ${saved_CMAKE_INCLUDE_PATH})
431
IF (MKL_LIBRARIES AND MKL_INCLUDE_DIR)
433
ELSE (MKL_LIBRARIES AND MKL_INCLUDE_DIR)
434
if (MKL_LIBRARIES AND NOT MKL_INCLUDE_DIR)
435
MESSAGE(WARNING "MKL libraries files are found, but MKL header files are \
436
not. You can get them by `conda install mkl-include` if using conda (if \
437
it is missing, run `conda upgrade -n root conda` first), and \
438
`pip install mkl-devel` if using pip. If build fails with header files \
439
available in the system, please make sure that CMake will search the \
440
directory containing them, e.g., by setting CMAKE_INCLUDE_PATH.")
443
SET(MKL_VERSION) # clear MKL_VERSION
444
ENDIF (MKL_LIBRARIES AND MKL_INCLUDE_DIR)
446
# Standard termination
447
IF(NOT MKL_FOUND AND MKL_FIND_REQUIRED)
448
MESSAGE(FATAL_ERROR "MKL library not found. Please specify library location \
449
by appending the root directory of the MKL installation to the environment variable CMAKE_PREFIX_PATH.")
450
ENDIF(NOT MKL_FOUND AND MKL_FIND_REQUIRED)
451
IF(NOT MKL_FIND_QUIETLY)
453
MESSAGE(STATUS "MKL library found")
455
MESSAGE(STATUS "MKL library not found")
457
ENDIF(NOT MKL_FIND_QUIETLY)
459
# Do nothing if MKL_FOUND was set before!