How to avoid OpenMP RTL mismatch if MKL and OpenMP are used

Hello everybody,

I stumbled upon a problem which I couldn’t immediately solve by reading the documentation of FindBLAS and FindOpenMP. Maybe someone here has a hint for me.
Let’s say I have project which imports an interface target A with BLAS dependency. FindBLAS determines MKL to be a good fit. Now, in my CMakeLists.txt I construct another target B which requires OpenMP. Then I link A to be B.
My concrete problem is that on Linux with GCC as compiler FindBLAS uses Intel’s OpenMP implementation and sets MKL’s interface layer accordingly (which is also what is suggested by the MKL Link Advisor).
FindOpenMP of course falls back to libgomp for linking. During linking I then end up using both runtime libraries, i.e. libgomp and libiomp, which I find somewhat dangerous. Here a reduced CMakeLists.txt that illustrates the problem:

cmake_minimum_required(VERSION 3.12)
project(test LANGUAGES C CXX)
 
find_package(BLAS REQUIRED)
find_package(OpenMP REQUIRED)

# Dummy interface libary A that depends on MKL
add_library(a INTERFACE)
target_include_directories(a INTERFACE include/)
target_link_libraries(a INTERFACE "${BLAS_LIBRARIES}")
target_link_options(a INTERFACE "${LINKER_FLAGS}")

# target B that depends on OpenMP and A
add_executable(b src/b.cc)
target_link_libraries(b PRIVATE OpenMP::OpenMP_CXX a)

Output is as follows:
– The C compiler identification is GNU 9.1.0
– The CXX compiler identification is GNU 9.1.0
– Check for working C compiler: /opt/bwhpc/common/compiler/gnu/9.1.0/bin/gcc
– Check for working C compiler: /opt/bwhpc/common/compiler/gnu/9.1.0/bin/gcc – works
– Detecting C compiler ABI info
– Detecting C compiler ABI info - done
– Detecting C compile features
– Detecting C compile features - done
– Check for working CXX compiler: /opt/bwhpc/common/compiler/gnu/9.1.0/bin/g++
– Check for working CXX compiler: /opt/bwhpc/common/compiler/gnu/9.1.0/bin/g++ – works
– Detecting CXX compiler ABI info
– Detecting CXX compiler ABI info - done
– Detecting CXX compile features
– Detecting CXX compile features - done
– Looking for sgemm_
– Looking for sgemm_ - not found
– Looking for pthread.h
– Looking for pthread.h - found
– Looking for pthread_create
– Looking for pthread_create - not found
– Looking for pthread_create in pthreads
– Looking for pthread_create in pthreads - not found
– Looking for pthread_create in pthread
– Looking for pthread_create in pthread - found
– Found Threads: TRUE
– Looking for sgemm_
– Looking for sgemm_ - found
– Found BLAS: /opt/bwhpc/common/compiler/intel/compxe.2018.5.274/compilers_and_libraries_2018.5.274/linux/mkl/lib/intel64_lin/libmkl_intel_lp64.so;/opt/bwhpc/common/compiler/intel/compxe.2018.5.274/compilers_and_libraries_2018.5.274/linux/mkl/lib/intel64_lin/libmkl_intel_thread.so;/opt/bwhpc/common/compiler/intel/compxe.2018.5.274/compilers_and_libraries_2018.5.274/linux/mkl/lib/intel64_lin/libmkl_core.so;/opt/bwhpc/common/compiler/intel/compxe.2018.5.274/compilers_and_libraries_2018.5.274/linux/compiler/lib/intel64_lin/libiomp5.so;-lpthread;-lm;-ldl
– Found OpenMP_C: -fopenmp (found version “4.5”)
– Found OpenMP_CXX: -fopenmp (found version “4.5”)
– Found OpenMP: TRUE (found version “4.5”)
– Configuring done
– Generating done

And building yields:

$ VERBOSE=1 make
/pfs/data1/software_uc1/bwhpc/common/devel/cmake/3.14.0/bin/cmake -S/home/hd/hd_hd/hd_em426/psidm2 -B/home/hd/hd_hd/hd_em426/psidm2/build --check-build-system CMakeFiles/Makefile.cmake 0
/pfs/data1/software_uc1/bwhpc/common/devel/cmake/3.14.0/bin/cmake -E cmake_progress_start /home/hd/hd_hd/hd_em426/psidm2/build/CMakeFiles /home/hd/hd_hd/hd_em426/psidm2/build/CMakeFiles/progress.marks
make -f CMakeFiles/Makefile2 all
make[1]: Entering directory /pfs/data2/home/hd/hd_hd/hd_em426/psidm2/build' make -f CMakeFiles/b.dir/build.make CMakeFiles/b.dir/depend make[2]: Entering directory /pfs/data2/home/hd/hd_hd/hd_em426/psidm2/build’
cd /home/hd/hd_hd/hd_em426/psidm2/build && /pfs/data1/software_uc1/bwhpc/common/devel/cmake/3.14.0/bin/cmake -E cmake_depends “Unix Makefiles” /home/hd/hd_hd/hd_em426/psidm2 /home/hd/hd_hd/hd_em426/psidm2 /home/hd/hd_hd/hd_em426/psidm2/build /home/hd/hd_hd/hd_em426/psidm2/build /home/hd/hd_hd/hd_em426/psidm2/build/CMakeFiles/b.dir/DependInfo.cmake --color=
Dependee “/home/hd/hd_hd/hd_em426/psidm2/build/CMakeFiles/b.dir/DependInfo.cmake” is newer than depender “/home/hd/hd_hd/hd_em426/psidm2/build/CMakeFiles/b.dir/depend.internal”.
Dependee “/home/hd/hd_hd/hd_em426/psidm2/build/CMakeFiles/CMakeDirectoryInformation.cmake” is newer than depender “/home/hd/hd_hd/hd_em426/psidm2/build/CMakeFiles/b.dir/depend.internal”.
Scanning dependencies of target b
make[2]: Leaving directory /pfs/data2/home/hd/hd_hd/hd_em426/psidm2/build' make -f CMakeFiles/b.dir/build.make CMakeFiles/b.dir/build make[2]: Entering directory /pfs/data2/home/hd/hd_hd/hd_em426/psidm2/build’
[ 50%] Building CXX object CMakeFiles/b.dir/src/b.cc.o
/opt/bwhpc/common/compiler/gnu/9.1.0/bin/g++ -I/home/hd/hd_hd/hd_em426/psidm2/include -fopenmp -o CMakeFiles/b.dir/src/b.cc.o -c /home/hd/hd_hd/hd_em426/psidm2/src/b.cc
[100%] Linking CXX executable b
/pfs/data1/software_uc1/bwhpc/common/devel/cmake/3.14.0/bin/cmake -E cmake_link_script CMakeFiles/b.dir/link.txt --verbose=1
/opt/bwhpc/common/compiler/gnu/9.1.0/bin/g++ CMakeFiles/b.dir/src/b.cc.o -o b /pfs/data1/software_uc1/bwhpc/common/compiler/gnu/9.1.0/lib64/libgomp.so -lpthread -lmkl_intel_lp64 -lmkl_intel_thread -lmkl_core /opt/bwhpc/common/compiler/intel/compxe.2018.5.274/compilers_and_libraries_2018.5.274/linux/compiler/lib/intel64_lin/libiomp5.so -lpthread -lm -ldl

So I guess my question is: Is this the intended behaviour of FindBLAS? Wouldn’t it be better for FindBLAS to select MKL’s GNU interface and use libgomp if it detects a GNU compiler so that mixing with FindOpenMP results not in the problem discussed above?