Publishing 2019 R1 content
[platform/upstream/dldt.git] / inference-engine / thirdparty / mkl-dnn / cmake / MKL.cmake
1 #===============================================================================
2 # Copyright 2016-2018 Intel Corporation
3 #
4 # Licensed under the Apache License, Version 2.0 (the "License");
5 # you may not use this file except in compliance with the License.
6 # You may obtain a copy of the License at
7 #
8 #     http://www.apache.org/licenses/LICENSE-2.0
9 #
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS,
12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 # See the License for the specific language governing permissions and
14 # limitations under the License.
15 #===============================================================================
16
17 # Locate Intel(R) MKL installation using MKLROOT or look in
18 # ${CMAKE_CURRENT_SOURCE_DIR}/external
19 #===============================================================================
20
21 if(MKL_cmake_included)
22     return()
23 endif()
24 set(MKL_cmake_included true)
25 include("cmake/utils.cmake")
26 include("cmake/options.cmake")
27
28 # set SKIP_THIS_MKL to true if given configuration is not supported
29 function(maybe_skip_this_mkl LIBNAME)
30     # Optimism...
31     set(SKIP_THIS_MKL False PARENT_SCOPE)
32
33     # Both mklml_intel and mklml_gnu are OpenMP based.
34     # So in case of TBB link with Intel MKL (RT library) and either set:
35     #   MKL_THREADING_LAYER=tbb
36     # to make Intel MKL use TBB threading as well, or
37     #   MKL_THREADING_LAYER=sequential
38     # to make Intel MKL be sequential.
39     if (MKLDNN_THREADING STREQUAL "TBB" AND LIBNAME MATCHES "mklml")
40         set(SKIP_THIS_MKL True PARENT_SCOPE)
41     endif()
42
43     # user doesn't want Intel MKL at all
44     if (MKLDNN_USE_MKL STREQUAL "NONE")
45         set(SKIP_THIS_MKL True PARENT_SCOPE)
46     endif()
47
48     # user specifies Intel MKL-ML should be used
49     if (MKLDNN_USE_MKL STREQUAL "ML")
50         if (LIBNAME STREQUAL "mkl_rt")
51             set(SKIP_THIS_MKL True PARENT_SCOPE)
52         endif()
53     endif()
54
55     # user specifies full Intel MKL should be used
56     if (MKLDNN_USE_MKL MATCHES "FULL")
57         if (LIBNAME MATCHES "mklml")
58             set(SKIP_THIS_MKL True PARENT_SCOPE)
59         endif()
60     endif()
61
62     # avoid using Intel MKL-ML that is not compatible with compiler's OpenMP RT
63     if (MKLDNN_THREADING STREQUAL "OMP:COMP")
64         if ((LIBNAME STREQUAL "mklml_intel" OR LIBNAME STREQUAL "mklml")
65                 AND (NOT CMAKE_CXX_COMPILER_ID STREQUAL "Intel"))
66             set(SKIP_THIS_MKL True PARENT_SCOPE)
67         elseif (LIBNAME STREQUAL "mklml_gnu"
68                 AND (NOT CMAKE_CXX_COMPILER_ID STREQUAL "GNU"))
69             set(SKIP_THIS_MKL True PARENT_SCOPE)
70         endif()
71     elseif (MKLDNN_THREADING STREQUAL "OMP:INTEL")
72        if (LIBNAME STREQUAL "mklml_gnu")
73            set(SKIP_THIS_MKL True PARENT_SCOPE)
74        endif()
75     endif()
76 endfunction()
77
78 function(detect_mkl LIBNAME)
79     if(HAVE_MKL)
80         return()
81     endif()
82
83     maybe_skip_this_mkl(${LIBNAME})
84     set_if(SKIP_THIS_MKL MAYBE_SKIP_MSG "... skipped")
85     message(STATUS "Detecting Intel(R) MKL: trying ${LIBNAME}${MAYBE_SKIP_MSG}")
86
87     if (SKIP_THIS_MKL)
88         return()
89     endif()
90
91     find_path(MKLINC mkl_cblas.h
92         HINTS ${MKLROOT}/include $ENV{MKLROOT}/include)
93
94     # skip full Intel MKL while looking for Intel MKL-ML
95     if (MKLINC AND LIBNAME MATCHES "mklml")
96         get_filename_component(__mklinc_root "${MKLINC}" PATH)
97         find_library(tmp_MKLLIB NAMES "mkl_rt"
98             HINTS ${__mklinc_root}/lib/intel64)
99         set_if(tmp_MKLLIB MKLINC "")
100         unset(tmp_MKLLIB CACHE)
101     endif()
102
103     if(NOT MKLINC)
104         file(GLOB_RECURSE MKLINC
105                 ${CMAKE_CURRENT_SOURCE_DIR}/external/*/mkl_cblas.h)
106         if(MKLINC)
107             # if user has multiple version under external/ then guess last
108             # one alphabetically is "latest" and warn
109             list(LENGTH MKLINC MKLINCLEN)
110             if(MKLINCLEN GREATER 1)
111                 list(SORT MKLINC)
112                 list(REVERSE MKLINC)
113                 list(GET MKLINC 0 MKLINCLST)
114                 set(MKLINC "${MKLINCLST}")
115             endif()
116             get_filename_component(MKLINC ${MKLINC} PATH)
117         endif()
118     endif()
119     if(NOT MKLINC)
120         return()
121     endif()
122
123     get_filename_component(__mklinc_root "${MKLINC}" PATH)
124     find_library(MKLLIB NAMES ${LIBNAME}
125         HINTS   ${MKLROOT}/lib ${MKLROOT}/lib/intel64
126                 $ENV{MKLROOT}/lib $ENV{MKLROOT}/lib/intel64
127                 ${__mklinc_root}/lib ${__mklinc_root}/lib/intel64)
128     if(NOT MKLLIB)
129         return()
130     endif()
131
132     if(WIN32)
133         set(MKLREDIST ${MKLINC}/../../redist/)
134         find_file(MKLDLL NAMES ${LIBNAME}.dll
135             HINTS
136                 ${MKLREDIST}/mkl
137                 ${MKLREDIST}/intel64/mkl
138                 ${__mklinc_root}/lib)
139         if(NOT MKLDLL)
140             return()
141         endif()
142     endif()
143
144     if(NOT CMAKE_CXX_COMPILER_ID STREQUAL "Intel")
145         get_filename_component(MKLLIBPATH ${MKLLIB} PATH)
146         find_library(MKLIOMP5LIB
147             NAMES "iomp5" "iomp5md" "libiomp5" "libiomp5md"
148             HINTS   ${MKLLIBPATH}
149                     ${MKLLIBPATH}/../../lib
150                     ${MKLLIBPATH}/../../../lib/intel64
151                     ${MKLLIBPATH}/../../compiler/lib
152                     ${MKLLIBPATH}/../../../compiler/lib/intel64)
153         if(NOT MKLIOMP5LIB)
154             return()
155         endif()
156         if(WIN32)
157             find_file(MKLIOMP5DLL
158                 NAMES "libiomp5.dll" "libiomp5md.dll"
159                 HINTS ${MKLREDIST}/../compiler ${__mklinc_root}/lib)
160             if(NOT MKLIOMP5DLL)
161                 return()
162             endif()
163         endif()
164     else()
165         set(MKLIOMP5LIB)
166         set(MKLIOMP5DLL)
167     endif()
168
169     get_filename_component(MKLLIBPATH "${MKLLIB}" PATH)
170     string(FIND "${MKLLIBPATH}" ${CMAKE_CURRENT_SOURCE_DIR}/external __idx)
171     if(${__idx} EQUAL 0)
172         if(WIN32)
173             install(PROGRAMS ${MKLDLL} ${MKLIOMP5DLL}
174                 DESTINATION ${CMAKE_INSTALL_BINDIR})
175         else()
176             install(PROGRAMS ${MKLLIB} ${MKLIOMP5LIB}
177                 DESTINATION ${CMAKE_INSTALL_LIBDIR})
178         endif()
179     endif()
180
181     if(WIN32)
182         # Add paths to DLL to %PATH% on Windows
183         get_filename_component(MKLDLLPATH "${MKLDLL}" PATH)
184         append_to_windows_path_list(CTESTCONFIG_PATH "${MKLDLLPATH}")
185         set(CTESTCONFIG_PATH "${CTESTCONFIG_PATH}" PARENT_SCOPE)
186     endif()
187
188     # TODO: cache the value
189     set(HAVE_MKL TRUE PARENT_SCOPE)
190     set(MKLINC ${MKLINC} PARENT_SCOPE)
191     set(MKLLIB "${MKLLIB}" PARENT_SCOPE)
192     set(MKLDLL "${MKLDLL}" PARENT_SCOPE)
193     if(LIBNAME MATCHES "mklml")
194         set(MKLDNN_USES_MKL "MKLML:SHARED" PARENT_SCOPE)
195     else()
196         set(MKLDNN_USES_MKL "FULL:SHARED" PARENT_SCOPE)
197     endif()
198
199     set(MKLIOMP5LIB "${MKLIOMP5LIB}" PARENT_SCOPE)
200     set(MKLIOMP5DLL "${MKLIOMP5DLL}" PARENT_SCOPE)
201 endfunction()
202
203 function(set_static_mkl_libs libpath)
204     set_ternary(lib WIN32 "" "lib")
205     set_ternary(a WIN32 ".lib" ".a")
206
207     if (MKLDNN_THREADING STREQUAL "TBB")
208         set(thr_name "tbb_thread")
209     elseif (MKLDNN_THREADING STREQUAL "OMP:COMP" AND CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
210         set(thr_name "gnu_thread")
211     else()
212         set(thr_name "intel_thread")
213     endif()
214
215     find_library(mkl_iface NAMES "${lib}mkl_intel_lp64${a}" HINTS ${libpath})
216     find_library(mkl_thr   NAMES "${lib}mkl_${thr_name}${a}" HINTS ${libpath})
217     find_library(mkl_core  NAMES "${lib}mkl_core${a}" HINTS ${libpath})
218
219     set(MKLLIB "${mkl_iface};${mkl_thr};${mkl_core}")
220     if (UNIX AND NOT APPLE)
221         list(APPEND MKLLIB "${mkl_iface};${mkl_thr};${mkl_core}")
222     endif()
223     set_if(UNIX MKLLIB "${MKLLIB};m;dl")
224     set(MKLLIB "${MKLLIB}" PARENT_SCOPE)
225 endfunction()
226
227 set(MKLDNN_USES_MKL "")
228 detect_mkl("mklml_intel")
229 detect_mkl("mklml_gnu")
230 detect_mkl("mklml")
231 detect_mkl("mkl_rt")
232
233 if(HAVE_MKL)
234     if (MKLDNN_USE_MKL STREQUAL "FULL:STATIC")
235         set(MKLDLL "")
236         get_filename_component(MKLLIBPATH "${MKLLIB}" PATH)
237         set_static_mkl_libs(${MKLLIBPATH})
238         list(APPEND EXTRA_STATIC_LIBS ${MKLLIB})
239         set(MKLDNN_USES_MKL "FULL:STATIC")
240     else()
241         list(APPEND EXTRA_SHARED_LIBS ${MKLLIB})
242     endif()
243
244     add_definitions(-DUSE_MKL -DUSE_CBLAS)
245     include_directories(AFTER ${MKLINC})
246
247     set(MSG "Intel(R) MKL:")
248     message(STATUS "${MSG} include ${MKLINC}")
249     message(STATUS "${MSG} lib ${MKLLIB}")
250     if(WIN32 AND MKLDLL)
251         message(STATUS "${MSG} dll ${MKLDLL}")
252     endif()
253 else()
254     if (MKLDNN_USE_MKL STREQUAL "NONE")
255         return()
256     endif()
257
258     if (NOT MKLDNN_USE_MKL STREQUAL "DEF")
259         set(FAIL_WITHOUT_MKL True)
260     endif()
261
262     if(DEFINED ENV{FAIL_WITHOUT_MKL} OR DEFINED FAIL_WITHOUT_MKL)
263         set(SEVERITY "FATAL_ERROR")
264     else()
265         set(SEVERITY "WARNING")
266     endif()
267     message(${SEVERITY}
268         "Intel(R) MKL not found. Some performance features may not be "
269         "available. Please run scripts/prepare_mkl.sh to download a minimal "
270         "set of libraries or get a full version from "
271         "https://software.intel.com/en-us/intel-mkl")
272 endif()