summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.circleci/config.yml5
-rwxr-xr-x.jenkins/pytorch/build-asan.sh16
-rwxr-xr-x.jenkins/pytorch/macos-test.sh8
-rw-r--r--CMakeLists.txt7
-rw-r--r--caffe2/CMakeLists.txt7
-rw-r--r--cmake/Dependencies.cmake80
-rw-r--r--cmake/Modules/FindMKL.cmake132
-rw-r--r--cmake/Modules/FindOpenMP.cmake635
-rw-r--r--cmake/Modules/README.md34
-rw-r--r--cmake/Summary.cmake1
-rw-r--r--modules/detectron/CMakeLists.txt8
-rw-r--r--torch/CMakeLists.txt12
12 files changed, 848 insertions, 97 deletions
diff --git a/.circleci/config.yml b/.circleci/config.yml
index a15c937f42..a17539fce6 100644
--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -184,7 +184,7 @@ setup_ci_environment: &setup_ci_environment
eval $(aws ecr get-login --region us-east-1 --no-include-email)
macos_brew_update: &macos_brew_update
- name: Brew update and install moreutils and expect
+ name: Brew update and install moreutils, expect and libomp
no_output_timeout: "1h"
command: |
set -ex
@@ -198,6 +198,7 @@ macos_brew_update: &macos_brew_update
brew install moreutils
brew link parallel --overwrite
brew install expect
+ brew install libomp
##############################################################################
@@ -246,7 +247,7 @@ pytorch_linux_test_defaults: &pytorch_linux_test_defaults
<<: *setup_ci_environment
- run:
name: Test
- no_output_timeout: "1h"
+ no_output_timeout: "90m"
command: |
set -e
export COMMIT_DOCKER_IMAGE=${DOCKER_IMAGE}-${CIRCLE_SHA1}
diff --git a/.jenkins/pytorch/build-asan.sh b/.jenkins/pytorch/build-asan.sh
index 174b4db099..c29fce0c1a 100755
--- a/.jenkins/pytorch/build-asan.sh
+++ b/.jenkins/pytorch/build-asan.sh
@@ -14,9 +14,23 @@ clang --version
# symbolize=1: Gives us much better errors when things go wrong
export ASAN_OPTIONS=detect_leaks=0:symbolize=1
+# FIXME: Remove the hardcoded "-pthread" option.
+# With asan build, the cmake thread CMAKE_HAVE_LIBC_CREATE[1] checking will
+# succeed because "pthread_create" is in libasan.so. However, libasan doesn't
+# have the full pthread implementation. Other advanced pthread functions doesn't
+# exist in libasan.so[2]. If we need some pthread advanced functions, we still
+# need to link the pthread library.
+# This issue is already fixed in cmake 3.13[3]. If we use the newer cmake, we
+# could remove this hardcoded option.
+#
+# [1] https://github.com/Kitware/CMake/blob/8cabaaf054a16ea9c8332ce8e9291bd026b38c62/Modules/FindThreads.cmake#L135
+# [2] https://wiki.gentoo.org/wiki/AddressSanitizer/Problems
+# [3] https://github.com/Kitware/CMake/commit/e9a1ddc594de6e6251bf06d732775dae2cabe4c8
+#
# TODO: Make the ASAN flags a more unified env var
CC="clang" CXX="clang++" LDSHARED="clang --shared" \
- CFLAGS="-fsanitize=address -fsanitize=undefined -fno-sanitize-recover=all -shared-libasan" \
+ CFLAGS="-fsanitize=address -fsanitize=undefined -fno-sanitize-recover=all -shared-libasan -pthread" \
+ CXX_FLAGS="-pthread" \
NO_CUDA=1 USE_MKLDNN=0 \
python setup.py install
diff --git a/.jenkins/pytorch/macos-test.sh b/.jenkins/pytorch/macos-test.sh
index 265dad5cd0..9ad943605d 100755
--- a/.jenkins/pytorch/macos-test.sh
+++ b/.jenkins/pytorch/macos-test.sh
@@ -50,6 +50,14 @@ if [ -z "${IN_CIRCLECI}" ]; then
7z x ${IMAGE_COMMIT_TAG}.7z -o"${PYTORCH_ENV_DIR}/miniconda3/lib/python3.6/site-packages"
fi
+# Test that OpenMP is enabled
+pushd test
+if [[ ! $(python -c "import torch; print(int(torch.backends.openmp.is_available()))") == "1" ]]; then
+ echo "Build should have OpenMP enabled, but torch.backends.openmp.is_available() is False"
+ exit 1
+fi
+popd
+
test_python_all() {
echo "Ninja version: $(ninja --version)"
python test/run_test.py --verbose
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 867de519b9..68e2e45bfd 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -2,6 +2,11 @@ cmake_minimum_required(VERSION 3.5 FATAL_ERROR)
#cmake_policy(SET CMP0022 NEW)
#cmake_policy(SET CMP0023 NEW)
+# Use compiler ID "AppleClang" instead of "Clang" for XCode.
+# Not setting this sometimes makes XCode C compiler gets detected as "Clang",
+# even when the C++ one is detected as "AppleClang".
+cmake_policy(SET CMP0025 NEW)
+
# ---[ Project and semantic versioning.
project(Caffe2 CXX C)
@@ -125,7 +130,7 @@ option(USE_NUMPY "Use NumPy" ON)
option(USE_OBSERVERS "Use observers module." OFF)
option(USE_OPENCL "Use OpenCL" OFF)
option(USE_OPENCV "Use OpenCV" ON)
-option(USE_OPENMP "Use OpenMP for parallel code" OFF)
+option(USE_OPENMP "Use OpenMP for parallel code" ON)
option(USE_PROF "Use profiling" OFF)
option(USE_QNNPACK "Use QNNPACK (quantized 8-bit operators)" ON)
option(USE_REDIS "Use Redis" OFF)
diff --git a/caffe2/CMakeLists.txt b/caffe2/CMakeLists.txt
index fe8e04a894..43af0060c1 100644
--- a/caffe2/CMakeLists.txt
+++ b/caffe2/CMakeLists.txt
@@ -224,6 +224,13 @@ if(NOT BUILD_ATEN_ONLY)
endif()
endif()
+if (USE_OPENMP AND OPENMP_FOUND)
+ message(STATUS "Caffe2 is compiling with OpenMP. \n"
+ "OpenMP CXX_FLAGS: ${OpenMP_CXX_FLAGS}. \n"
+ "OpenMP libraries: ${OpenMP_CXX_LIBRARIES}.")
+ target_link_libraries(caffe2 PRIVATE ${OpenMP_CXX_LIBRARIES})
+endif()
+
target_link_libraries(caffe2 PUBLIC c10)
target_link_libraries(caffe2 PUBLIC ${Caffe2_PUBLIC_DEPENDENCY_LIBS})
target_link_libraries(caffe2 PRIVATE ${Caffe2_DEPENDENCY_LIBS})
diff --git a/cmake/Dependencies.cmake b/cmake/Dependencies.cmake
index 2ff910f5aa..7ab15fb5cf 100644
--- a/cmake/Dependencies.cmake
+++ b/cmake/Dependencies.cmake
@@ -107,6 +107,10 @@ elseif(BLAS STREQUAL "MKL")
endif()
include(${CMAKE_CURRENT_LIST_DIR}/public/mkl.cmake)
if(MKL_FOUND)
+ message(STATUS "MKL libraries: ${MKL_LIBRARIES}")
+ message(STATUS "MKL include directory: ${MKL_INCLUDE_DIR}")
+ message(STATUS "MKL OpenMP type: ${MKL_OPENMP_TYPE}")
+ message(STATUS "MKL OpenMP library: ${MKL_OPENMP_LIBRARY}")
include_directories(SYSTEM ${MKL_INCLUDE_DIR})
list(APPEND Caffe2_PUBLIC_DEPENDENCY_LIBS caffe2::mkl)
set(CAFFE2_USE_MKL ON)
@@ -670,12 +674,45 @@ endif()
# ---[ OpenMP
if(USE_OPENMP)
- find_package(OpenMP)
+ # OpenMP support?
+ SET(WITH_OPENMP ON CACHE BOOL "OpenMP support if available?")
+
+ # macOS + GCC
+ IF (APPLE AND CMAKE_COMPILER_IS_GNUCC)
+ EXEC_PROGRAM (uname ARGS -v OUTPUT_VARIABLE DARWIN_VERSION)
+ STRING (REGEX MATCH "[0-9]+" DARWIN_VERSION ${DARWIN_VERSION})
+ MESSAGE (STATUS "macOS Darwin version: ${DARWIN_VERSION}")
+ IF (DARWIN_VERSION GREATER 9)
+ SET(APPLE_OPENMP_SUCKS 1)
+ ENDIF (DARWIN_VERSION GREATER 9)
+ EXECUTE_PROCESS (COMMAND ${CMAKE_C_COMPILER} -dumpversion
+ OUTPUT_VARIABLE GCC_VERSION)
+ IF (APPLE_OPENMP_SUCKS AND GCC_VERSION VERSION_LESS 4.6.2)
+ MESSAGE(WARNING "Disabling OpenMP (unstable with this version of GCC). "
+ "Install GCC >= 4.6.2 or change your OS to enable OpenMP.")
+ add_compile_options(-Wno-unknown-pragmas)
+ SET(WITH_OPENMP OFF CACHE BOOL "OpenMP support if available?" FORCE)
+ ENDIF()
+ ENDIF()
+
+ IF (WITH_OPENMP AND NOT CHECKED_OPENMP)
+ FIND_PACKAGE(OpenMP QUIET)
+ SET(CHECKED_OPENMP ON CACHE BOOL "already checked for OpenMP")
+
+ # OPENMP_FOUND is not cached in FindOpenMP.cmake (all other variables are cached)
+ # see https://github.com/Kitware/CMake/blob/master/Modules/FindOpenMP.cmake
+ SET(OPENMP_FOUND ${OPENMP_FOUND} CACHE BOOL "OpenMP Support found")
+ ENDIF()
+
if(OPENMP_FOUND)
- message(STATUS "Adding " ${OpenMP_CXX_FLAGS})
+ message(STATUS "Adding OpenMP CXX_FLAGS: " ${OpenMP_CXX_FLAGS})
+ IF("${OpenMP_CXX_LIBRARIES}" STREQUAL "")
+ message(STATUS "No OpenMP library needs to be linked against")
+ ELSE()
+ message(STATUS "Will link against OpenMP libraries: ${OpenMP_CXX_LIBRARIES}")
+ ENDIF()
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS}")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}")
- set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${OpenMP_EXE_LINKER_FLAGS}")
else()
message(WARNING "Not compiling with OpenMP. Suppress this warning with -DUSE_OPENMP=OFF")
caffe2_update_option(USE_OPENMP OFF)
@@ -1096,43 +1133,6 @@ if (NOT BUILD_ATEN_MOBILE)
STRING(REGEX REPLACE "[-/]DNDEBUG" "" CMAKE_CXX_FLAGS_RELEASE "" ${CMAKE_CXX_FLAGS_RELEASE})
ENDIF()
- # OpenMP support?
- SET(WITH_OPENMP ON CACHE BOOL "OpenMP support if available?")
-
- # macOS + GCC
- IF (APPLE AND CMAKE_COMPILER_IS_GNUCC)
- EXEC_PROGRAM (uname ARGS -v OUTPUT_VARIABLE DARWIN_VERSION)
- STRING (REGEX MATCH "[0-9]+" DARWIN_VERSION ${DARWIN_VERSION})
- MESSAGE (STATUS "macOS Darwin version: ${DARWIN_VERSION}")
- IF (DARWIN_VERSION GREATER 9)
- SET(APPLE_OPENMP_SUCKS 1)
- ENDIF (DARWIN_VERSION GREATER 9)
- EXECUTE_PROCESS (COMMAND ${CMAKE_C_COMPILER} -dumpversion
- OUTPUT_VARIABLE GCC_VERSION)
- IF (APPLE_OPENMP_SUCKS AND GCC_VERSION VERSION_LESS 4.6.2)
- MESSAGE(WARNING "Disabling OpenMP (unstable with this version of GCC). "
- "Install GCC >= 4.6.2 or change your OS to enable OpenMP.")
- add_compile_options(-Wno-unknown-pragmas)
- SET(WITH_OPENMP OFF CACHE BOOL "OpenMP support if available?" FORCE)
- ENDIF()
- ENDIF()
-
- IF (WITH_OPENMP AND NOT CHECKED_OPENMP)
- FIND_PACKAGE(OpenMP)
- SET(CHECKED_OPENMP ON CACHE BOOL "already checked for OpenMP")
-
- # OPENMP_FOUND is not cached in FindOpenMP.cmake (all other variables are cached)
- # see https://github.com/Kitware/CMake/blob/master/Modules/FindOpenMP.cmake
- SET(OPENMP_FOUND ${OPENMP_FOUND} CACHE BOOL "OpenMP Support found")
- ENDIF()
-
- IF (OPENMP_FOUND)
- MESSAGE(STATUS "Compiling with OpenMP support")
- SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS}")
- SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}")
- ENDIF()
-
-
SET(CUDA_ATTACH_VS_BUILD_RULE_TO_CUDA_FILE OFF)
FIND_PACKAGE(MAGMA)
diff --git a/cmake/Modules/FindMKL.cmake b/cmake/Modules/FindMKL.cmake
index fb7a716446..3be472ca0f 100644
--- a/cmake/Modules/FindMKL.cmake
+++ b/cmake/Modules/FindMKL.cmake
@@ -5,6 +5,8 @@
# MKL_VERSION - best guess of the found mkl version
# MKL_INCLUDE_DIR - path to include dir.
# MKL_LIBRARIES - list of libraries for base mkl
+# MKL_OPENMP_TYPE - OpenMP flavor that the found mkl uses: GNU or Intel
+# MKL_OPENMP_LIBRARY - path to the OpenMP library the found mkl uses
# MKL_LAPACK_LIBRARIES - list of libraries to add for lapack
# MKL_SCALAPACK_LIBRARIES - list of libraries to add for scalapack
# MKL_SOLVER_LIBRARIES - list of libraries to add for the solvers
@@ -16,6 +18,8 @@ IF (NOT MKL_FOUND)
SET(MKL_VERSION)
SET(MKL_INCLUDE_DIR)
SET(MKL_LIBRARIES)
+SET(MKL_OPENMP_TYPE)
+SET(MKL_OPENMP_LIBRARY)
SET(MKL_LAPACK_LIBRARIES)
SET(MKL_SCALAPACK_LIBRARIES)
SET(MKL_SOLVER_LIBRARIES)
@@ -103,7 +107,7 @@ IF (EXISTS ${INTEL_MKL_DIR})
ENDIF()
# Try linking multiple libs
-MACRO(CHECK_ALL_LIBRARIES LIBRARIES _name _list _flags)
+MACRO(CHECK_ALL_LIBRARIES LIBRARIES OPENMP_TYPE OPENMP_LIBRARY _name _list _flags)
# This macro checks for the existence of the combination of libraries given by _list.
# If the combination is found, this macro checks whether we can link against that library
# combination using the name of a routine given by _name using the linker
@@ -116,30 +120,60 @@ MACRO(CHECK_ALL_LIBRARIES LIBRARIES _name _list _flags)
# start checking
SET(_libraries_work TRUE)
SET(${LIBRARIES})
+ SET(${OPENMP_TYPE})
+ SET(${OPENMP_LIBRARY})
SET(_combined_name)
+ SET(_openmp_type)
+ SET(_openmp_library)
SET(_paths)
- set(__list)
- foreach(_elem ${_list})
- if(__list)
- set(__list "${__list} - ${_elem}")
- else(__list)
- set(__list "${_elem}")
- endif(__list)
- endforeach(_elem)
IF (NOT MKL_FIND_QUIETLY)
- message(STATUS "Checking for [${__list}]")
+ set(_str_list)
+ foreach(_elem ${_list})
+ if(_str_list)
+ set(_str_list "${_str_list} - ${_elem}")
+ else()
+ set(_str_list "${_elem}")
+ endif()
+ endforeach(_elem)
+ message(STATUS "Checking for [${_str_list}]")
ENDIF ()
FOREACH(_library ${_list})
SET(_combined_name ${_combined_name}_${_library})
+ UNSET(${_prefix}_${_library}_LIBRARY)
IF(_libraries_work)
- IF(${_library} STREQUAL "gomp")
- FIND_PACKAGE(OpenMP)
+ IF(${_library} MATCHES "omp")
+ IF(_openmp_type)
+ MESSAGE(FATAL_ERROR "More than one OpenMP libraries appear in the MKL test: ${_list}")
+ ELSEIF(${_library} MATCHES "gomp")
+ SET(_openmp_type "GNU")
+ # Use FindOpenMP to find gomp
+ FIND_PACKAGE(OpenMP QUIET)
IF(OPENMP_FOUND)
- SET(${_prefix}_${_library}_LIBRARY ${OpenMP_C_FLAGS})
+ # Test that none of the found library names contains "iomp" (Intel
+ # OpenMP). This doesn't necessarily mean that we have gomp... but it
+ # is probably good enough since on gcc we should already have
+ # OpenMP_CXX_FLAGS="-fopenmp" and OpenMP_CXX_LIB_NAMES="".
+ SET(_found_gomp true)
+ FOREACH(_lib_name ${OpenMP_CXX_LIB_NAMES})
+ IF (_found_gomp AND "${_lib_name}" MATCHES "iomp")
+ SET(_found_gomp false)
+ ENDIF()
+ ENDFOREACH()
+ IF(_found_gomp)
+ SET(${_prefix}_${_library}_LIBRARY ${OpenMP_CXX_FLAGS})
+ SET(_openmp_library "${${_prefix}_${_library}_LIBRARY}")
+ ENDIF()
ENDIF(OPENMP_FOUND)
- ELSE(${_library} STREQUAL "gomp")
+ ELSEIF(${_library} MATCHES "iomp")
+ SET(_openmp_type "Intel")
FIND_LIBRARY(${_prefix}_${_library}_LIBRARY NAMES ${_library})
- ENDIF(${_library} STREQUAL "gomp")
+ SET(_openmp_library "${${_prefix}_${_library}_LIBRARY}")
+ ELSE()
+ MESSAGE(FATAL_ERROR "Unknown OpenMP flavor: ${_library}")
+ ENDIF()
+ ELSE(${_library} MATCHES "omp")
+ FIND_LIBRARY(${_prefix}_${_library}_LIBRARY NAMES ${_library})
+ ENDIF(${_library} MATCHES "omp")
MARK_AS_ADVANCED(${_prefix}_${_library}_LIBRARY)
SET(${LIBRARIES} ${${LIBRARIES}} ${${_prefix}_${_library}_LIBRARY})
SET(_libraries_work ${${_prefix}_${_library}_LIBRARY})
@@ -163,6 +197,10 @@ MACRO(CHECK_ALL_LIBRARIES LIBRARIES _name _list _flags)
ENDIF(_libraries_work)
# Fin
IF(_libraries_work)
+ SET(${OPENMP_TYPE} ${_openmp_type})
+ MARK_AS_ADVANCED(${OPENMP_TYPE})
+ SET(${OPENMP_LIBRARY} ${_openmp_library})
+ MARK_AS_ADVANCED(${OPENMP_LIBRARY})
ELSE (_libraries_work)
SET(${LIBRARIES})
MARK_AS_ADVANCED(${LIBRARIES})
@@ -187,48 +225,52 @@ ENDIF(UNIX AND NOT APPLE)
IF (NOT MKL_LIBRARIES)
SET(MKL_VERSION 1011)
ENDIF (NOT MKL_LIBRARIES)
-FOREACH(mklrtl ${mklrtls} "")
- FOREACH(mkliface ${mklifaces})
- FOREACH(mkl64 ${mkl64s} "")
- FOREACH(mklthread ${mklthreads})
- IF (NOT MKL_LIBRARIES AND NOT INTEL_MKL_SEQUENTIAL)
- CHECK_ALL_LIBRARIES(MKL_LIBRARIES cblas_sgemm
- "mkl_${mkliface}${mkl64};${mklthread};mkl_core;${mklrtl};${mkl_pthread};${mkl_m};${mkl_dl}" "")
- ENDIF (NOT MKL_LIBRARIES AND NOT INTEL_MKL_SEQUENTIAL)
- ENDFOREACH(mklthread)
- ENDFOREACH(mkl64)
- ENDFOREACH(mkliface)
-ENDFOREACH(mklrtl)
+
+# First: search for parallelized ones with intel thread lib
+IF (NOT INTEL_MKL_SEQUENTIAL)
+ FOREACH(mklrtl ${mklrtls} "")
+ FOREACH(mkliface ${mklifaces})
+ FOREACH(mkl64 ${mkl64s} "")
+ FOREACH(mklthread ${mklthreads})
+ IF (NOT MKL_LIBRARIES)
+ CHECK_ALL_LIBRARIES(MKL_LIBRARIES MKL_OPENMP_TYPE MKL_OPENMP_LIBRARY cblas_sgemm
+ "mkl_${mkliface}${mkl64};${mklthread};mkl_core;${mklrtl};${mkl_pthread};${mkl_m};${mkl_dl}" "")
+ ENDIF (NOT MKL_LIBRARIES)
+ ENDFOREACH(mklthread)
+ ENDFOREACH(mkl64)
+ ENDFOREACH(mkliface)
+ ENDFOREACH(mklrtl)
+ENDIF (NOT INTEL_MKL_SEQUENTIAL)
+
+# Second: search for sequential ones
+FOREACH(mkliface ${mklifaces})
+ FOREACH(mkl64 ${mkl64s} "")
+ IF (NOT MKL_LIBRARIES)
+ CHECK_ALL_LIBRARIES(MKL_LIBRARIES MKL_OPENMP_TYPE MKL_OPENMP_LIBRARY cblas_sgemm
+ "mkl_${mkliface}${mkl64};mkl_sequential;mkl_core;${mkl_m};${mkl_dl}" "")
+ IF (MKL_LIBRARIES)
+ SET(mklseq "_sequential")
+ ENDIF (MKL_LIBRARIES)
+ ENDIF (NOT MKL_LIBRARIES)
+ ENDFOREACH(mkl64)
+ENDFOREACH(mkliface)
+
+# First: search for parallelized ones with native pthread lib
FOREACH(mklrtl ${mklrtls} "")
FOREACH(mkliface ${mklifaces})
FOREACH(mkl64 ${mkl64s} "")
IF (NOT MKL_LIBRARIES)
- CHECK_ALL_LIBRARIES(MKL_LIBRARIES cblas_sgemm
- "mkl_${mkliface}${mkl64};mkl_sequential;mkl_core;${mkl_m};${mkl_dl}" "")
- IF (MKL_LIBRARIES)
- SET(mklseq "_sequential")
- ENDIF (MKL_LIBRARIES)
+ CHECK_ALL_LIBRARIES(MKL_LIBRARIES MKL_OPENMP_TYPE MKL_OPENMP_LIBRARY cblas_sgemm
+ "mkl_${mkliface}${mkl64};${mklthread};mkl_core;${mklrtl};pthread;${mkl_m};${mkl_dl}" "")
ENDIF (NOT MKL_LIBRARIES)
ENDFOREACH(mkl64)
ENDFOREACH(mkliface)
ENDFOREACH(mklrtl)
-FOREACH(mklrtl ${mklrtls} "")
- FOREACH(mkliface ${mklifaces})
- FOREACH(mkl64 ${mkl64s} "")
- FOREACH(mklthread ${mklthreads})
- IF (NOT MKL_LIBRARIES)
- CHECK_ALL_LIBRARIES(MKL_LIBRARIES cblas_sgemm
- "mkl_${mkliface}${mkl64};${mklthread};mkl_core;${mklrtl};pthread;${mkl_m};${mkl_dl}" "")
- ENDIF (NOT MKL_LIBRARIES)
- ENDFOREACH(mklthread)
- ENDFOREACH(mkl64)
- ENDFOREACH(mkliface)
-ENDFOREACH(mklrtl)
# Check for older versions
IF (NOT MKL_LIBRARIES)
SET(MKL_VERSION 900)
- CHECK_ALL_LIBRARIES(MKL_LIBRARIES cblas_sgemm
+ CHECK_ALL_LIBRARIES(MKL_LIBRARIES MKL_OPENMP_TYPE MKL_OPENMP_LIBRARY cblas_sgemm
"mkl;guide;pthread;m" "")
ENDIF (NOT MKL_LIBRARIES)
diff --git a/cmake/Modules/FindOpenMP.cmake b/cmake/Modules/FindOpenMP.cmake
new file mode 100644
index 0000000000..5aace85139
--- /dev/null
+++ b/cmake/Modules/FindOpenMP.cmake
@@ -0,0 +1,635 @@
+# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+# file Copyright.txt or https://cmake.org/licensing for details.
+
+#.rst:
+# FindOpenMP
+# ----------
+#
+# Finds OpenMP support
+#
+# This module can be used to detect OpenMP support in a compiler. If
+# the compiler supports OpenMP, the flags required to compile with
+# OpenMP support are returned in variables for the different languages.
+# The variables may be empty if the compiler does not need a special
+# flag to support OpenMP.
+#
+# Variables
+# ^^^^^^^^^
+#
+# The module exposes the components ``C``, ``CXX``, and ``Fortran``.
+# Each of these controls the various languages to search OpenMP support for.
+#
+# Depending on the enabled components the following variables will be set:
+#
+# ``OpenMP_FOUND``
+# Variable indicating that OpenMP flags for all requested languages have been found.
+# If no components are specified, this is true if OpenMP settings for all enabled languages
+# were detected.
+# ``OpenMP_VERSION``
+# Minimal version of the OpenMP standard detected among the requested languages,
+# or all enabled languages if no components were specified.
+#
+# This module will set the following variables per language in your
+# project, where ``<lang>`` is one of C, CXX, or Fortran:
+#
+# ``OpenMP_<lang>_FOUND``
+# Variable indicating if OpenMP support for ``<lang>`` was detected.
+# ``OpenMP_<lang>_FLAGS``
+# OpenMP compiler flags for ``<lang>``, separated by spaces.
+#
+# For linking with OpenMP code written in ``<lang>``, the following
+# variables are provided:
+#
+# ``OpenMP_<lang>_LIB_NAMES``
+# :ref:`;-list <CMake Language Lists>` of libraries for OpenMP programs for ``<lang>``.
+# ``OpenMP_<libname>_LIBRARY``
+# Location of the individual libraries needed for OpenMP support in ``<lang>``.
+# ``OpenMP_<lang>_LIBRARIES``
+# A list of libraries needed to link with OpenMP code written in ``<lang>``.
+#
+# Additionally, the module provides :prop_tgt:`IMPORTED` targets:
+#
+# ``OpenMP::OpenMP_<lang>``
+# Target for using OpenMP from ``<lang>``.
+#
+# Specifically for Fortran, the module sets the following variables:
+#
+# ``OpenMP_Fortran_HAVE_OMPLIB_HEADER``
+# Boolean indicating if OpenMP is accessible through ``omp_lib.h``.
+# ``OpenMP_Fortran_HAVE_OMPLIB_MODULE``
+# Boolean indicating if OpenMP is accessible through the ``omp_lib`` Fortran module.
+#
+# The module will also try to provide the OpenMP version variables:
+#
+# ``OpenMP_<lang>_SPEC_DATE``
+# Date of the OpenMP specification implemented by the ``<lang>`` compiler.
+# ``OpenMP_<lang>_VERSION_MAJOR``
+# Major version of OpenMP implemented by the ``<lang>`` compiler.
+# ``OpenMP_<lang>_VERSION_MINOR``
+# Minor version of OpenMP implemented by the ``<lang>`` compiler.
+# ``OpenMP_<lang>_VERSION``
+# OpenMP version implemented by the ``<lang>`` compiler.
+#
+# The specification date is formatted as given in the OpenMP standard:
+# ``yyyymm`` where ``yyyy`` and ``mm`` represents the year and month of
+# the OpenMP specification implemented by the ``<lang>`` compiler.
+
+cmake_policy(PUSH)
+cmake_policy(SET CMP0012 NEW) # if() recognizes numbers and booleans
+cmake_policy(SET CMP0054 NEW) # if() quoted variables not dereferenced
+cmake_policy(SET CMP0057 NEW) # if IN_LIST
+
+function(_OPENMP_FLAG_CANDIDATES LANG)
+ if(NOT OpenMP_${LANG}_FLAG)
+ unset(OpenMP_FLAG_CANDIDATES)
+
+ set(OMP_FLAG_GNU "-fopenmp")
+ set(OMP_FLAG_Clang "-fopenmp=libomp" "-fopenmp=libiomp5" "-fopenmp")
+
+ # AppleClang may need a header file, search for omp.h with hints to brew
+ # default include dir
+ find_path(__header_dir "omp.h" HINTS "/usr/local/include")
+ set(OMP_FLAG_AppleClang "-Xpreprocessor -fopenmp" "-Xpreprocessor -fopenmp -I${__header_dir}")
+
+ set(OMP_FLAG_HP "+Oopenmp")
+ if(WIN32)
+ set(OMP_FLAG_Intel "-Qopenmp")
+ elseif(CMAKE_${LANG}_COMPILER_ID STREQUAL "Intel" AND
+ "${CMAKE_${LANG}_COMPILER_VERSION}" VERSION_LESS "15.0.0.20140528")
+ set(OMP_FLAG_Intel "-openmp")
+ else()
+ set(OMP_FLAG_Intel "-qopenmp")
+ endif()
+ set(OMP_FLAG_MIPSpro "-mp")
+ set(OMP_FLAG_MSVC "-openmp")
+ set(OMP_FLAG_PathScale "-openmp")
+ set(OMP_FLAG_NAG "-openmp")
+ set(OMP_FLAG_Absoft "-openmp")
+ set(OMP_FLAG_PGI "-mp")
+ set(OMP_FLAG_Flang "-fopenmp")
+ set(OMP_FLAG_SunPro "-xopenmp")
+ set(OMP_FLAG_XL "-qsmp=omp")
+ # Cray compiler activate OpenMP with -h omp, which is enabled by default.
+ set(OMP_FLAG_Cray " " "-h omp")
+
+ # If we know the correct flags, use those
+ if(DEFINED OMP_FLAG_${CMAKE_${LANG}_COMPILER_ID})
+ set(OpenMP_FLAG_CANDIDATES "${OMP_FLAG_${CMAKE_${LANG}_COMPILER_ID}}")
+ # Fall back to reasonable default tries otherwise
+ else()
+ set(OpenMP_FLAG_CANDIDATES "-openmp" "-fopenmp" "-mp" " ")
+ endif()
+ set(OpenMP_${LANG}_FLAG_CANDIDATES "${OpenMP_FLAG_CANDIDATES}" PARENT_SCOPE)
+ else()
+ set(OpenMP_${LANG}_FLAG_CANDIDATES "${OpenMP_${LANG}_FLAG}" PARENT_SCOPE)
+ endif()
+endfunction()
+
+# sample openmp source code to test
+set(OpenMP_C_CXX_TEST_SOURCE
+"
+#include <omp.h>
+int main(void) {
+#ifdef _OPENMP
+ omp_get_max_threads();
+ return 0;
+#else
+ breaks_on_purpose
+#endif
+}
+")
+
+# in Fortran, an implementation may provide an omp_lib.h header
+# or omp_lib module, or both (OpenMP standard, section 3.1)
+# Furthmore !$ is the Fortran equivalent of #ifdef _OPENMP (OpenMP standard, 2.2.2)
+# Without the conditional compilation, some compilers (e.g. PGI) might compile OpenMP code
+# while not actually enabling OpenMP, building code sequentially
+set(OpenMP_Fortran_TEST_SOURCE
+ "
+ program test
+ @OpenMP_Fortran_INCLUDE_LINE@
+ !$ integer :: n
+ n = omp_get_num_threads()
+ end program test
+ "
+)
+
+function(_OPENMP_WRITE_SOURCE_FILE LANG SRC_FILE_CONTENT_VAR SRC_FILE_NAME SRC_FILE_FULLPATH)
+ set(WORK_DIR ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/FindOpenMP)
+ if("${LANG}" STREQUAL "C")
+ set(SRC_FILE "${WORK_DIR}/${SRC_FILE_NAME}.c")
+ file(WRITE "${SRC_FILE}" "${OpenMP_C_CXX_${SRC_FILE_CONTENT_VAR}}")
+ elseif("${LANG}" STREQUAL "CXX")
+ set(SRC_FILE "${WORK_DIR}/${SRC_FILE_NAME}.cpp")
+ file(WRITE "${SRC_FILE}" "${OpenMP_C_CXX_${SRC_FILE_CONTENT_VAR}}")
+ elseif("${LANG}" STREQUAL "Fortran")
+ set(SRC_FILE "${WORK_DIR}/${SRC_FILE_NAME}.f90")
+ file(WRITE "${SRC_FILE}_in" "${OpenMP_Fortran_${SRC_FILE_CONTENT_VAR}}")
+ configure_file("${SRC_FILE}_in" "${SRC_FILE}" @ONLY)
+ endif()
+ set(${SRC_FILE_FULLPATH} "${SRC_FILE}" PARENT_SCOPE)
+endfunction()
+
+include(CMakeParseImplicitLinkInfo)
+
+function(_OPENMP_GET_FLAGS LANG FLAG_MODE OPENMP_FLAG_VAR OPENMP_LIB_NAMES_VAR)
+ _OPENMP_FLAG_CANDIDATES("${LANG}")
+ _OPENMP_WRITE_SOURCE_FILE("${LANG}" "TEST_SOURCE" OpenMPTryFlag _OPENMP_TEST_SRC)
+
+ unset(OpenMP_VERBOSE_COMPILE_OPTIONS)
+ if(UNIX)
+ separate_arguments(OpenMP_VERBOSE_OPTIONS UNIX_COMMAND "${CMAKE_${LANG}_VERBOSE_FLAG}")
+ else()
+ separate_arguments(OpenMP_VERBOSE_OPTIONS WINDOWS_COMMAND "${CMAKE_${LANG}_VERBOSE_FLAG}")
+ endif()
+ foreach(_VERBOSE_OPTION IN LISTS OpenMP_VERBOSE_OPTIONS)
+ if(NOT _VERBOSE_OPTION MATCHES "^-Wl,")
+ list(APPEND OpenMP_VERBOSE_COMPILE_OPTIONS ${_VERBOSE_OPTION})
+ endif()
+ endforeach()
+
+ foreach(OPENMP_FLAG IN LISTS OpenMP_${LANG}_FLAG_CANDIDATES)
+ set(OPENMP_FLAGS_TEST "${OPENMP_FLAG}")
+ if(OpenMP_VERBOSE_COMPILE_OPTIONS)
+ string(APPEND OPENMP_FLAGS_TEST " ${OpenMP_VERBOSE_COMPILE_OPTIONS}")
+ endif()
+ string(REGEX REPLACE "[-/=+]" "" OPENMP_PLAIN_FLAG "${OPENMP_FLAG}")
+
+ # NOTE [ Linking both MKL and OpenMP ]
+ #
+ # It is crucial not to link two `libomp` libraries together, even when they
+ # are both Intel or GNU. Otherwise, you will end up with this nasty error,
+ # and may get incorrect results.
+ #
+ # OMP: Error #15: Initializing libomp.dylib, but found libiomp5.dylib
+ # already initialized.
+ #
+ # OMP: Hint This means that multiple copies of the OpenMP runtime have
+ # been linked into the program. That is dangerous, since it can degrade
+ # performance or cause incorrect results. The best thing to do is to
+ # ensure that only a single OpenMP runtime is linked into the process,
+ # e.g. by avoiding static linking of the OpenMP runtime in any library. As
+ # an unsafe, unsupported, undocumented workaround you can set the
+ # environment variable KMP_DUPLICATE_LIB_OK=TRUE to allow the program to
+ # continue to execute, but that may cause crashes or silently produce
+ # incorrect results. For more information, please see
+ # http://openmp.llvm.org/
+ #
+ # So here, before we test each flag combination, we first try directly
+ # linking against any `libomp` MKL has found (if any). This allows us to
+ # do sensible things in tricky (yet common) conditions like:
+ # - using `clang` (so no native GNU OpenMP), and
+ # - having `brew` `libomp` installed at `/usr/local/`, and
+ # - having `conda` `mkl` installed at `$HOME/conda/`, with includes a copy
+ # of `libiomp5`.
+ # Rather than blindly picking one, we pick what ever `FindMKL.cmake` choses
+ # to avoid conflicts.
+ #
+ # Crucially, we only do so for non-GNU compilers. For GNU ones,
+ # `FindMKL.cmake` calls `FindOpenMP.cmake` when trying to find `gomp` and
+ # thus will cause infinite recursion if this is not taken care of. Moreover,
+ # for them, since the compiler provices the OpenMP library, it is most
+ # likely that only one viable gomp library can be found in search path by
+ # `FindOpenMP.cmake`, so the chance of having conflicts is slow.
+ #
+ # TODO: refactor to solve this weird dependency where
+ # - for non-GNU, FindOpenMP.cmake replies on FindMKL.cmake to finish first, but
+ # - for GNU, FindMKL.cmake replies on FindOpenMP.cmake to finish first.
+
+ if(NOT "${CMAKE_${LANG}_COMPILER_ID}" STREQUAL "GNU")
+ find_package(MKL QUIET)
+ if(MKL_FOUND AND (NOT "${MKL_OPENMP_LIBRARY}" STREQUAL ""))
+ # If we already link OpenMP via MKL, use that. Otherwise at run-time
+ # OpenMP will complain about being initialized twice (OMP: Error #15),
+ # can may cause incorrect behavior.
+ set(OpenMP_libomp_LIBRARY "${MKL_OPENMP_LIBRARY}" CACHE STRING "libomp location for OpenMP")
+ else()
+ find_library(OpenMP_libomp_LIBRARY
+ NAMES omp gomp iomp5
+ HINTS ${CMAKE_${LANG}_IMPLICIT_LINK_DIRECTORIES}
+ DOC "libomp location for OpenMP"
+ )
+ endif()
+ mark_as_advanced(OpenMP_libomp_LIBRARY)
+
+ if (OpenMP_libomp_LIBRARY)
+ try_compile( OpenMP_COMPILE_RESULT_${FLAG_MODE}_${OPENMP_PLAIN_FLAG} ${CMAKE_BINARY_DIR} ${_OPENMP_TEST_SRC}
+ CMAKE_FLAGS "-DCOMPILE_DEFINITIONS:STRING=${OPENMP_FLAGS_TEST}"
+ LINK_LIBRARIES ${CMAKE_${LANG}_VERBOSE_FLAG} ${OpenMP_libomp_LIBRARY}
+ OUTPUT_VARIABLE OpenMP_TRY_COMPILE_OUTPUT
+ )
+ if(OpenMP_COMPILE_RESULT_${FLAG_MODE}_${OPENMP_PLAIN_FLAG})
+ set("${OPENMP_FLAG_VAR}" "${OPENMP_FLAG}" PARENT_SCOPE)
+ set("${OPENMP_LIB_NAMES_VAR}" "libomp" PARENT_SCOPE)
+ break()
+ endif()
+ endif()
+ endif()
+
+ try_compile( OpenMP_COMPILE_RESULT_${FLAG_MODE}_${OPENMP_PLAIN_FLAG} ${CMAKE_BINARY_DIR} ${_OPENMP_TEST_SRC}
+ CMAKE_FLAGS "-DCOMPILE_DEFINITIONS:STRING=${OPENMP_FLAGS_TEST}"
+ LINK_LIBRARIES ${CMAKE_${LANG}_VERBOSE_FLAG}
+ OUTPUT_VARIABLE OpenMP_TRY_COMPILE_OUTPUT
+ )
+
+ if(OpenMP_COMPILE_RESULT_${FLAG_MODE}_${OPENMP_PLAIN_FLAG})
+ set("${OPENMP_FLAG_VAR}" "${OPENMP_FLAG}" PARENT_SCOPE)
+
+ if(CMAKE_${LANG}_VERBOSE_FLAG)
+ unset(OpenMP_${LANG}_IMPLICIT_LIBRARIES)
+ unset(OpenMP_${LANG}_IMPLICIT_LINK_DIRS)
+ unset(OpenMP_${LANG}_IMPLICIT_FWK_DIRS)
+ unset(OpenMP_${LANG}_LOG_VAR)
+
+ file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log
+ "Detecting ${LANG} OpenMP compiler ABI info compiled with the following output:\n${OpenMP_TRY_COMPILE_OUTPUT}\n\n")
+
+ cmake_parse_implicit_link_info("${OpenMP_TRY_COMPILE_OUTPUT}"
+ OpenMP_${LANG}_IMPLICIT_LIBRARIES
+ OpenMP_${LANG}_IMPLICIT_LINK_DIRS
+ OpenMP_${LANG}_IMPLICIT_FWK_DIRS
+ OpenMP_${LANG}_LOG_VAR
+ "${CMAKE_${LANG}_IMPLICIT_OBJECT_REGEX}"
+ )
+
+ file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log
+ "Parsed ${LANG} OpenMP implicit link information from above output:\n${OpenMP_${LANG}_LOG_VAR}\n\n")
+
+ unset(_OPENMP_LIB_NAMES)
+ foreach(_OPENMP_IMPLICIT_LIB IN LISTS OpenMP_${LANG}_IMPLICIT_LIBRARIES)
+ get_filename_component(_OPENMP_IMPLICIT_LIB_DIR "${_OPENMP_IMPLICIT_LIB}" DIRECTORY)
+ get_filename_component(_OPENMP_IMPLICIT_LIB_NAME "${_OPENMP_IMPLICIT_LIB}" NAME)
+ get_filename_component(_OPENMP_IMPLICIT_LIB_PLAIN "${_OPENMP_IMPLICIT_LIB}" NAME_WE)
+ string(REGEX REPLACE "([][+.*?()^$])" "\\\\\\1" _OPENMP_IMPLICIT_LIB_PLAIN_ESC "${_OPENMP_IMPLICIT_LIB_PLAIN}")
+ string(REGEX REPLACE "([][+.*?()^$])" "\\\\\\1" _OPENMP_IMPLICIT_LIB_PATH_ESC "${_OPENMP_IMPLICIT_LIB}")
+ if(NOT ( "${_OPENMP_IMPLICIT_LIB}" IN_LIST CMAKE_${LANG}_IMPLICIT_LINK_LIBRARIES
+ OR "${CMAKE_${LANG}_STANDARD_LIBRARIES}" MATCHES "(^| )(-Wl,)?(-l)?(${_OPENMP_IMPLICIT_LIB_PLAIN_ESC}|${_OPENMP_IMPLICIT_LIB_PATH_ESC})( |$)"
+ OR "${CMAKE_${LANG}_LINK_EXECUTABLE}" MATCHES "(^| )(-Wl,)?(-l)?(${_OPENMP_IMPLICIT_LIB_PLAIN_ESC}|${_OPENMP_IMPLICIT_LIB_PATH_ESC})( |$)" ) )
+ if(_OPENMP_IMPLICIT_LIB_DIR)
+ set(OpenMP_${_OPENMP_IMPLICIT_LIB_PLAIN}_LIBRARY "${_OPENMP_IMPLICIT_LIB}" CACHE FILEPATH
+ "Path to the ${_OPENMP_IMPLICIT_LIB_PLAIN} library for OpenMP")
+ else()
+ find_library(OpenMP_${_OPENMP_IMPLICIT_LIB_PLAIN}_LIBRARY
+ NAMES "${_OPENMP_IMPLICIT_LIB_NAME}"
+ DOC "Path to the ${_OPENMP_IMPLICIT_LIB_PLAIN} library for OpenMP"
+ HINTS ${OpenMP_${LANG}_IMPLICIT_LINK_DIRS}
+ CMAKE_FIND_ROOT_PATH_BOTH
+ NO_DEFAULT_PATH
+ )
+ endif()
+ mark_as_advanced(OpenMP_${_OPENMP_IMPLICIT_LIB_PLAIN}_LIBRARY)
+ list(APPEND _OPENMP_LIB_NAMES ${_OPENMP_IMPLICIT_LIB_PLAIN})
+ endif()
+ endforeach()
+ set("${OPENMP_LIB_NAMES_VAR}" "${_OPENMP_LIB_NAMES}" PARENT_SCOPE)
+ else()
+ # We do not know how to extract implicit OpenMP libraries for this compiler.
+ # Assume that it handles them automatically, e.g. the Intel Compiler on
+ # Windows should put the dependency in its object files.
+ set("${OPENMP_LIB_NAMES_VAR}" "" PARENT_SCOPE)
+ endif()
+ break()
+ elseif((CMAKE_${LANG}_COMPILER_ID STREQUAL "AppleClang") AND
+ (NOT CMAKE_${LANG}_COMPILER_VERSION VERSION_LESS "7.0"))
+
+ # LLVM 3.7 supports OpenMP 3.1, and continues to add more features to
+ # support newer OpenMP standards in new versions.
+ # http://releases.llvm.org/3.7.0/tools/clang/docs/ReleaseNotes.html#openmp-support
+ #
+ # Apple Clang 7.0 is the first version based on LLVM 3.7 or later.
+ # https://en.wikipedia.org/wiki/Xcode#Latest_versions
+ #
+ # Check for separate OpenMP library on AppleClang 7+
+ find_library(OpenMP_libomp_LIBRARY
+ NAMES omp gomp iomp5
+ HINTS ${CMAKE_${LANG}_IMPLICIT_LINK_DIRECTORIES}
+ DOC "libomp location for OpenMP"
+ )
+ mark_as_advanced(OpenMP_libomp_LIBRARY)
+
+ if(OpenMP_libomp_LIBRARY)
+ try_compile( OpenMP_COMPILE_RESULT_${FLAG_MODE}_${OPENMP_PLAIN_FLAG} ${CMAKE_BINARY_DIR} ${_OPENMP_TEST_SRC}
+ CMAKE_FLAGS "-DCOMPILE_DEFINITIONS:STRING=${OPENMP_FLAGS_TEST}"
+ LINK_LIBRARIES ${CMAKE_${LANG}_VERBOSE_FLAG} ${OpenMP_libomp_LIBRARY}
+ OUTPUT_VARIABLE OpenMP_TRY_COMPILE_OUTPUT
+ )
+ if(OpenMP_COMPILE_RESULT_${FLAG_MODE}_${OPENMP_PLAIN_FLAG})
+ set("${OPENMP_FLAG_VAR}" "${OPENMP_FLAG}" PARENT_SCOPE)
+ set("${OPENMP_LIB_NAMES_VAR}" "libomp" PARENT_SCOPE)
+ break()
+ endif()
+ endif()
+ else()
+ file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log
+ "Detecting ${LANG} OpenMP failed with the following output:\n${OpenMP_TRY_COMPILE_OUTPUT}\n\n")
+ endif()
+ if (NOT ${OpenMP_${LANG}_FIND_QUIETLY})
+ message(STATUS "OpenMP try_compile log:\n${OpenMP_TRY_COMPILE_OUTPUT}\n\n")
+ endif()
+ set("${OPENMP_LIB_NAMES_VAR}" "NOTFOUND" PARENT_SCOPE)
+ set("${OPENMP_FLAG_VAR}" "NOTFOUND" PARENT_SCOPE)
+ endforeach()
+
+ unset(OpenMP_VERBOSE_COMPILE_OPTIONS)
+endfunction()
+
+set(OpenMP_C_CXX_CHECK_VERSION_SOURCE
+"
+#include <stdio.h>
+#include <omp.h>
+const char ompver_str[] = { 'I', 'N', 'F', 'O', ':', 'O', 'p', 'e', 'n', 'M',
+ 'P', '-', 'd', 'a', 't', 'e', '[',
+ ('0' + ((_OPENMP/100000)%10)),
+ ('0' + ((_OPENMP/10000)%10)),
+ ('0' + ((_OPENMP/1000)%10)),
+ ('0' + ((_OPENMP/100)%10)),
+ ('0' + ((_OPENMP/10)%10)),
+ ('0' + ((_OPENMP/1)%10)),
+ ']', '\\0' };
+int main(void)
+{
+ puts(ompver_str);
+ return 0;
+}
+")
+
+set(OpenMP_Fortran_CHECK_VERSION_SOURCE
+"
+ program omp_ver
+ @OpenMP_Fortran_INCLUDE_LINE@
+ integer, parameter :: zero = ichar('0')
+ integer, parameter :: ompv = openmp_version
+ character, dimension(24), parameter :: ompver_str =&
+ (/ 'I', 'N', 'F', 'O', ':', 'O', 'p', 'e', 'n', 'M', 'P', '-',&
+ 'd', 'a', 't', 'e', '[',&
+ char(zero + mod(ompv/100000, 10)),&
+ char(zero + mod(ompv/10000, 10)),&
+ char(zero + mod(ompv/1000, 10)),&
+ char(zero + mod(ompv/100, 10)),&
+ char(zero + mod(ompv/10, 10)),&
+ char(zero + mod(ompv/1, 10)), ']' /)
+ print *, ompver_str
+ end program omp_ver
+")
+
+function(_OPENMP_GET_SPEC_DATE LANG SPEC_DATE)
+ _OPENMP_WRITE_SOURCE_FILE("${LANG}" "CHECK_VERSION_SOURCE" OpenMPCheckVersion _OPENMP_TEST_SRC)
+
+ set(BIN_FILE "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/FindOpenMP/ompver_${LANG}.bin")
+ string(REGEX REPLACE "[-/=+]" "" OPENMP_PLAIN_FLAG "${OPENMP_FLAG}")
+ try_compile(OpenMP_SPECTEST_${LANG}_${OPENMP_PLAIN_FLAG} "${CMAKE_BINARY_DIR}" "${_OPENMP_TEST_SRC}"
+ CMAKE_FLAGS "-DCOMPILE_DEFINITIONS:STRING=${OpenMP_${LANG}_FLAGS}"
+ COPY_FILE ${BIN_FILE}
+ OUTPUT_VARIABLE OpenMP_TRY_COMPILE_OUTPUT)
+
+ if(${OpenMP_SPECTEST_${LANG}_${OPENMP_PLAIN_FLAG}})
+ file(STRINGS ${BIN_FILE} specstr LIMIT_COUNT 1 REGEX "INFO:OpenMP-date")
+ set(regex_spec_date ".*INFO:OpenMP-date\\[0*([^]]*)\\].*")
+ if("${specstr}" MATCHES "${regex_spec_date}")
+ set(${SPEC_DATE} "${CMAKE_MATCH_1}" PARENT_SCOPE)
+ endif()
+ else()
+ file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log
+ "Detecting ${LANG} OpenMP version failed with the following output:\n${OpenMP_TRY_COMPILE_OUTPUT}\n\n")
+ endif()
+endfunction()
+
+macro(_OPENMP_SET_VERSION_BY_SPEC_DATE LANG)
+ set(OpenMP_SPEC_DATE_MAP
+ # Preview versions
+ "201611=5.0" # OpenMP 5.0 preview 1
+ # Combined versions, 2.5 onwards
+ "201511=4.5"
+ "201307=4.0"
+ "201107=3.1"
+ "200805=3.0"
+ "200505=2.5"
+ # C/C++ version 2.0
+ "200203=2.0"
+ # Fortran version 2.0
+ "200011=2.0"
+ # Fortran version 1.1
+ "199911=1.1"
+ # C/C++ version 1.0 (there's no 1.1 for C/C++)
+ "199810=1.0"
+ # Fortran version 1.0
+ "199710=1.0"
+ )
+
+ if(OpenMP_${LANG}_SPEC_DATE)
+ string(REGEX MATCHALL "${OpenMP_${LANG}_SPEC_DATE}=([0-9]+)\\.([0-9]+)" _version_match "${OpenMP_SPEC_DATE_MAP}")
+ else()
+ set(_version_match "")
+ endif()
+ if(NOT _version_match STREQUAL "")
+ set(OpenMP_${LANG}_VERSION_MAJOR ${CMAKE_MATCH_1})
+ set(OpenMP_${LANG}_VERSION_MINOR ${CMAKE_MATCH_2})
+ set(OpenMP_${LANG}_VERSION "${OpenMP_${LANG}_VERSION_MAJOR}.${OpenMP_${LANG}_VERSION_MINOR}")
+ else()
+ unset(OpenMP_${LANG}_VERSION_MAJOR)
+ unset(OpenMP_${LANG}_VERSION_MINOR)
+ unset(OpenMP_${LANG}_VERSION)
+ endif()
+ unset(_version_match)
+ unset(OpenMP_SPEC_DATE_MAP)
+endmacro()
+
+foreach(LANG IN ITEMS C CXX)
+ if(CMAKE_${LANG}_COMPILER_LOADED)
+ if(NOT DEFINED OpenMP_${LANG}_FLAGS OR "${OpenMP_${LANG}_FLAGS}" STREQUAL "NOTFOUND"
+ OR NOT DEFINED OpenMP_${LANG}_LIB_NAMES OR "${OpenMP_${LANG}_LIB_NAMES}" STREQUAL "NOTFOUND")
+ _OPENMP_GET_FLAGS("${LANG}" "${LANG}" OpenMP_${LANG}_FLAGS_WORK OpenMP_${LANG}_LIB_NAMES_WORK)
+ endif()
+
+ set(OpenMP_${LANG}_FLAGS "${OpenMP_${LANG}_FLAGS_WORK}"
+ CACHE STRING "${LANG} compiler flags for OpenMP parallelization")
+ set(OpenMP_${LANG}_LIB_NAMES "${OpenMP_${LANG}_LIB_NAMES_WORK}"
+ CACHE STRING "${LANG} compiler libraries for OpenMP parallelization")
+ mark_as_advanced(OpenMP_${LANG}_FLAGS OpenMP_${LANG}_LIB_NAMES)
+ endif()
+endforeach()
+
+if(CMAKE_Fortran_COMPILER_LOADED)
+ if(NOT DEFINED OpenMP_Fortran_FLAGS OR "${OpenMP_Fortran_FLAGS}" STREQUAL "NOTFOUND"
+ OR NOT DEFINED OpenMP_Fortran_LIB_NAMES OR "${OpenMP_Fortran_LIB_NAMES}" STREQUAL "NOTFOUND"
+ OR NOT DEFINED OpenMP_Fortran_HAVE_OMPLIB_MODULE)
+ set(OpenMP_Fortran_INCLUDE_LINE "use omp_lib\n implicit none")
+ _OPENMP_GET_FLAGS("Fortran" "FortranHeader" OpenMP_Fortran_FLAGS_WORK OpenMP_Fortran_LIB_NAMES_WORK)
+ if(OpenMP_Fortran_FLAGS_WORK)
+ set(OpenMP_Fortran_HAVE_OMPLIB_MODULE TRUE CACHE BOOL INTERNAL "")
+ endif()
+
+ set(OpenMP_Fortran_FLAGS "${OpenMP_Fortran_FLAGS_WORK}"
+ CACHE STRING "Fortran compiler flags for OpenMP parallelization")
+ set(OpenMP_Fortran_LIB_NAMES "${OpenMP_Fortran_LIB_NAMES_WORK}"
+ CACHE STRING "Fortran compiler libraries for OpenMP parallelization")
+ mark_as_advanced(OpenMP_Fortran_FLAGS OpenMP_Fortran_LIB_NAMES)
+ endif()
+
+ if(NOT DEFINED OpenMP_Fortran_FLAGS OR "${OpenMP_Fortran_FLAGS}" STREQUAL "NOTFOUND"
+ OR NOT DEFINED OpenMP_Fortran_LIB_NAMES OR "${OpenMP_Fortran_LIB_NAMES}" STREQUAL "NOTFOUND"
+ OR NOT DEFINED OpenMP_Fortran_HAVE_OMPLIB_HEADER)
+ set(OpenMP_Fortran_INCLUDE_LINE "implicit none\n include 'omp_lib.h'")
+ _OPENMP_GET_FLAGS("Fortran" "FortranModule" OpenMP_Fortran_FLAGS_WORK OpenMP_Fortran_LIB_NAMES_WORK)
+ if(OpenMP_Fortran_FLAGS_WORK)
+ set(OpenMP_Fortran_HAVE_OMPLIB_HEADER TRUE CACHE BOOL INTERNAL "")
+ endif()
+
+ set(OpenMP_Fortran_FLAGS "${OpenMP_Fortran_FLAGS_WORK}"
+ CACHE STRING "Fortran compiler flags for OpenMP parallelization")
+
+ set(OpenMP_Fortran_LIB_NAMES "${OpenMP_Fortran_LIB_NAMES}"
+ CACHE STRING "Fortran compiler libraries for OpenMP parallelization")
+ endif()
+
+ if(OpenMP_Fortran_HAVE_OMPLIB_MODULE)
+ set(OpenMP_Fortran_INCLUDE_LINE "use omp_lib\n implicit none")
+ else()
+ set(OpenMP_Fortran_INCLUDE_LINE "implicit none\n include 'omp_lib.h'")
+ endif()
+endif()
+
+if(NOT OpenMP_FIND_COMPONENTS)
+ set(OpenMP_FINDLIST C CXX Fortran)
+else()
+ set(OpenMP_FINDLIST ${OpenMP_FIND_COMPONENTS})
+endif()
+
+unset(_OpenMP_MIN_VERSION)
+
+include(FindPackageHandleStandardArgs)
+
+foreach(LANG IN LISTS OpenMP_FINDLIST)
+ if(CMAKE_${LANG}_COMPILER_LOADED)
+ if (NOT OpenMP_${LANG}_SPEC_DATE AND OpenMP_${LANG}_FLAGS)
+ _OPENMP_GET_SPEC_DATE("${LANG}" OpenMP_${LANG}_SPEC_DATE_INTERNAL)
+ set(OpenMP_${LANG}_SPEC_DATE "${OpenMP_${LANG}_SPEC_DATE_INTERNAL}" CACHE
+ INTERNAL "${LANG} compiler's OpenMP specification date")
+ _OPENMP_SET_VERSION_BY_SPEC_DATE("${LANG}")
+ endif()
+
+ set(OpenMP_${LANG}_FIND_QUIETLY ${OpenMP_FIND_QUIETLY})
+ set(OpenMP_${LANG}_FIND_REQUIRED ${OpenMP_FIND_REQUIRED})
+ set(OpenMP_${LANG}_FIND_VERSION ${OpenMP_FIND_VERSION})
+ set(OpenMP_${LANG}_FIND_VERSION_EXACT ${OpenMP_FIND_VERSION_EXACT})
+
+ set(_OPENMP_${LANG}_REQUIRED_VARS OpenMP_${LANG}_FLAGS)
+ if("${OpenMP_${LANG}_LIB_NAMES}" STREQUAL "NOTFOUND")
+ set(_OPENMP_${LANG}_REQUIRED_LIB_VARS OpenMP_${LANG}_LIB_NAMES)
+ else()
+ foreach(_OPENMP_IMPLICIT_LIB IN LISTS OpenMP_${LANG}_LIB_NAMES)
+ list(APPEND _OPENMP_${LANG}_REQUIRED_LIB_VARS OpenMP_${_OPENMP_IMPLICIT_LIB}_LIBRARY)
+ endforeach()
+ endif()
+
+ find_package_handle_standard_args(OpenMP_${LANG}
+ REQUIRED_VARS OpenMP_${LANG}_FLAGS ${_OPENMP_${LANG}_REQUIRED_LIB_VARS}
+ VERSION_VAR OpenMP_${LANG}_VERSION
+ )
+
+ if(OpenMP_${LANG}_FOUND)
+ if(DEFINED OpenMP_${LANG}_VERSION)
+ if(NOT _OpenMP_MIN_VERSION OR _OpenMP_MIN_VERSION VERSION_GREATER OpenMP_${LANG}_VERSION)
+ set(_OpenMP_MIN_VERSION OpenMP_${LANG}_VERSION)
+ endif()
+ endif()
+ set(OpenMP_${LANG}_LIBRARIES "")
+ foreach(_OPENMP_IMPLICIT_LIB IN LISTS OpenMP_${LANG}_LIB_NAMES)
+ list(APPEND OpenMP_${LANG}_LIBRARIES "${OpenMP_${_OPENMP_IMPLICIT_LIB}_LIBRARY}")
+ endforeach()
+
+ if(NOT TARGET OpenMP::OpenMP_${LANG})
+ add_library(OpenMP::OpenMP_${LANG} INTERFACE IMPORTED)
+ endif()
+ if(OpenMP_${LANG}_FLAGS)
+ if(UNIX)
+ separate_arguments(_OpenMP_${LANG}_OPTIONS UNIX_COMMAND "${OpenMP_${LANG}_FLAGS}")
+ else()
+ separate_arguments(_OpenMP_${LANG}_OPTIONS WINDOWS_COMMAND "${OpenMP_${LANG}_FLAGS}")
+ endif()
+ set_property(TARGET OpenMP::OpenMP_${LANG} PROPERTY
+ INTERFACE_COMPILE_OPTIONS "$<$<COMPILE_LANGUAGE:${LANG}>:${_OpenMP_${LANG}_OPTIONS}>")
+ unset(_OpenMP_${LANG}_OPTIONS)
+ endif()
+ if(OpenMP_${LANG}_LIBRARIES)
+ set_property(TARGET OpenMP::OpenMP_${LANG} PROPERTY
+ INTERFACE_LINK_LIBRARIES "${OpenMP_${LANG}_LIBRARIES}")
+ endif()
+ endif()
+ endif()
+endforeach()
+
+unset(_OpenMP_REQ_VARS)
+foreach(LANG IN ITEMS C CXX Fortran)
+ if((NOT OpenMP_FIND_COMPONENTS AND CMAKE_${LANG}_COMPILER_LOADED) OR LANG IN_LIST OpenMP_FIND_COMPONENTS)
+ list(APPEND _OpenMP_REQ_VARS "OpenMP_${LANG}_FOUND")
+ endif()
+endforeach()
+
+find_package_handle_standard_args(OpenMP
+ REQUIRED_VARS ${_OpenMP_REQ_VARS}
+ VERSION_VAR ${_OpenMP_MIN_VERSION}
+ HANDLE_COMPONENTS)
+
+set(OPENMP_FOUND ${OpenMP_FOUND})
+
+if(CMAKE_Fortran_COMPILER_LOADED AND OpenMP_Fortran_FOUND)
+ if(NOT DEFINED OpenMP_Fortran_HAVE_OMPLIB_MODULE)
+ set(OpenMP_Fortran_HAVE_OMPLIB_MODULE FALSE CACHE BOOL INTERNAL "")
+ endif()
+ if(NOT DEFINED OpenMP_Fortran_HAVE_OMPLIB_HEADER)
+ set(OpenMP_Fortran_HAVE_OMPLIB_HEADER FALSE CACHE BOOL INTERNAL "")
+ endif()
+endif()
+
+if(NOT ( CMAKE_C_COMPILER_LOADED OR CMAKE_CXX_COMPILER_LOADED OR CMAKE_Fortran_COMPILER_LOADED ))
+ message(SEND_ERROR "FindOpenMP requires the C, CXX or Fortran languages to be enabled")
+endif()
+
+unset(OpenMP_C_CXX_TEST_SOURCE)
+unset(OpenMP_Fortran_TEST_SOURCE)
+unset(OpenMP_C_CXX_CHECK_VERSION_SOURCE)
+unset(OpenMP_Fortran_CHECK_VERSION_SOURCE)
+unset(OpenMP_Fortran_INCLUDE_LINE)
+
+cmake_policy(POP)
diff --git a/cmake/Modules/README.md b/cmake/Modules/README.md
new file mode 100644
index 0000000000..df1ceb91a9
--- /dev/null
+++ b/cmake/Modules/README.md
@@ -0,0 +1,34 @@
+This folder contains various custom cmake modules for finding libraries and packages. Details about some of them are listed below.
+
+### [`FindOpenMP.cmake`](./FindOpenMP.cmake)
+
+This is modified from [the file included in CMake 3.13 release](https://github.com/Kitware/CMake/blob/05a2ca7f87b9ae73f373e9967fde1ee5210e33af/Modules/FindOpenMP.cmake), with the following changes:
+
++ Replace `VERSION_GREATER_EQUAL` with `NOT ... VERSION_LESS` as `VERSION_GREATER_EQUAL` is not supported in CMake 3.5 (our min supported version).
+
++ Update the `separate_arguments` commands to not use `NATIVE_COMMAND` which is not supported in CMake 3.5 (our min supported version).
+
++ Make it respect the `QUIET` flag so that, when it is set, `try_compile` failures are not reported.
+
++ For `AppleClang` compilers, use `-Xpreprocessor` instead of `-Xclang` as the later is not documented.
+
++ For `AppleClang` compilers, an extra flag option is tried, which is `-Xpreprocessor -openmp -I${DIR_OF_omp_h}`, where `${DIR_OF_omp_h}` is a obtained using `find_path` on `omp.h` with `brew`'s default include directory as a hint. Without this, the compiler will complain about missing headers as they are not natively included in Apple's LLVM.
+
++ For non-GNU compilers, whenever we try a candidate OpenMP flag, first try it with directly linking MKL's `libomp` if it has one. Otherwise, we may end up linking two `libomp`s and end up with this nasty error:
+
+ ```
+ OMP: Error #15: Initializing libomp.dylib, but found libiomp5.dylib already
+ initialized.
+
+ OMP: Hint This means that multiple copies of the OpenMP runtime have been
+ linked into the program. That is dangerous, since it can degrade performance
+ or cause incorrect results. The best thing to do is to ensure that only a
+ single OpenMP runtime is linked into the process, e.g. by avoiding static
+ linking of the OpenMP runtime in any library. As an unsafe, unsupported,
+ undocumented workaround you can set the environment variable
+ KMP_DUPLICATE_LIB_OK=TRUE to allow the program to continue to execute, but
+ that may cause crashes or silently produce incorrect results. For more
+ information, please see http://openmp.llvm.org/
+ ```
+
+ See NOTE [ Linking both MKL and OpenMP ] for details.
diff --git a/cmake/Summary.cmake b/cmake/Summary.cmake
index d687c6dc1f..0793526d64 100644
--- a/cmake/Summary.cmake
+++ b/cmake/Summary.cmake
@@ -7,6 +7,7 @@ function (caffe2_print_configuration_summary)
message(STATUS " CMake command : ${CMAKE_COMMAND}")
message(STATUS " System : ${CMAKE_SYSTEM_NAME}")
message(STATUS " C++ compiler : ${CMAKE_CXX_COMPILER}")
+ message(STATUS " C++ compiler id : ${CMAKE_CXX_COMPILER_ID}")
message(STATUS " C++ compiler version : ${CMAKE_CXX_COMPILER_VERSION}")
message(STATUS " BLAS : ${BLAS}")
message(STATUS " CXX flags : ${CMAKE_CXX_FLAGS}")
diff --git a/modules/detectron/CMakeLists.txt b/modules/detectron/CMakeLists.txt
index 8628c5fdaf..7d4861f574 100644
--- a/modules/detectron/CMakeLists.txt
+++ b/modules/detectron/CMakeLists.txt
@@ -2,6 +2,10 @@ file(GLOB Detectron_CPU_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/*.cc)
file(GLOB Detectron_GPU_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/*.cu)
if (BUILD_CAFFE2_OPS)
+ if (USE_OPENMP AND OPENMP_FOUND)
+ Set(OpenMP_link ${OpenMP_CXX_LIBRARIES})
+ endif()
+
# Note(ilijar): Since Detectron ops currently have no
# CPU implementation, we only build GPU ops for now.
if (USE_CUDA)
@@ -10,14 +14,14 @@ if (BUILD_CAFFE2_OPS)
${Detectron_CPU_SRCS}
${Detectron_GPU_SRCS})
- target_link_libraries(caffe2_detectron_ops_gpu caffe2_gpu)
+ target_link_libraries(caffe2_detectron_ops_gpu caffe2_gpu ${OpenMP_link})
install(TARGETS caffe2_detectron_ops_gpu DESTINATION lib)
if (MSVC)
install(FILES $<TARGET_PDB_FILE:caffe2_detectron_ops_gpu> DESTINATION lib OPTIONAL)
endif()
elseif(NOT IOS_PLATFORM)
add_library(caffe2_detectron_ops SHARED ${Detectron_CPU_SRCS})
- target_link_libraries(caffe2_detectron_ops caffe2)
+ target_link_libraries(caffe2_detectron_ops caffe2 ${OpenMP_link})
install(TARGETS caffe2_detectron_ops DESTINATION lib)
if (MSVC)
install(FILES $<TARGET_PDB_FILE:caffe2_detectron_ops> DESTINATION lib OPTIONAL)
diff --git a/torch/CMakeLists.txt b/torch/CMakeLists.txt
index 2f0beeccf5..347cb3d58c 100644
--- a/torch/CMakeLists.txt
+++ b/torch/CMakeLists.txt
@@ -314,13 +314,13 @@ endif()
target_link_libraries(torch caffe2_library)
-find_package(OpenMP)
+find_package(OpenMP QUIET)
if(OPENMP_FOUND)
- if (VERBOSE)
- message(STATUS "Compiling with OpenMP")
- endif()
- target_compile_options(torch INTERFACE -fopenmp)
- target_link_libraries(torch -fopenmp)
+ message(STATUS "pytorch is compiling with OpenMP. \n"
+ "OpenMP CXX_FLAGS: ${OpenMP_CXX_FLAGS}. \n"
+ "OpenMP libraries: ${OpenMP_CXX_LIBRARIES}.")
+ target_compile_options(torch INTERFACE ${OpenMP_CXX_FLAGS})
+ target_link_libraries(torch ${OpenMP_CXX_LIBRARIES})
endif()
if (NOT NO_API)