Skip to content
This repository has been archived by the owner on Nov 17, 2023. It is now read-only.

Cmake blas #14871

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -324,6 +324,8 @@ else()
endif()
endif()

include(cmake/ChooseBlas.cmake)

if(USE_ASAN)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fno-omit-frame-pointer -fsanitize=address")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-omit-frame-pointer -fsanitize=address")
Expand Down
2 changes: 1 addition & 1 deletion ci/docker/Dockerfile.build.android_armv8
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ ENV CXX=${CROSS_ROOT}/bin/${CROSS_TRIPLE}-clang++
# Build ARM dependencies.
COPY install/android_arm64_openblas.sh /work/
RUN /work/android_arm64_openblas.sh
ENV CPLUS_INCLUDE_PATH /work/deps/OpenBLAS
ENV OpenBLAS_HOME=/work/deps/OpenBLAS

ARG USER_ID=0
ARG GROUP_ID=0
Expand Down
41 changes: 37 additions & 4 deletions ci/docker/install/android_arm64_openblas.sh
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,41 @@ pushd .
git clone https://github.com/xianyi/OpenBLAS.git
cd OpenBLAS
make -j$(nproc) TARGET=ARMV8 ARM_SOFTFP_ABI=1 HOSTCC=gcc NOFORTRAN=1 libs
# Can't be run (utility not compiled for the target platform)
#make install
cp *.h /usr/include
cp libopenblas.a /usr/local/lib

# Ideally, a simple `make install` would do the job. However, OpenBLAS fails when running `make
# install` because it tries to execute `getarch`, which is an utility that is not compiled for the
# target platform.
#
# In order to not need to install the library we set the variable OpenBLAS_HOME in the exported
# docker image.
#
# An important gotcha here to explain the reason of not doing the `make install` by hand:
#
# given that the compiler is installed in a different path than the usual (as is the case when
# doing crosscompilation), then the compiler uses different paths to look for the includes and
# libraries. So it is necessary to install it into the correct directory of includes for the
# configured compiler ($CC and $CXX).

# For example, When querying the default include directories with the current docker image, I get:
#
# $ $CXX -Wp,-v -x c++ - -fsyntax-only
# clang -cc1 version 6.0.2 based upon LLVM 6.0.2svn default target x86_64-unknown-linux-gnu
# ignoring nonexistent directory "/usr/aarch64-linux-android/bin/.
# ./lib/gcc/aarch64-linux-android/4.9.x/../../../../include/c++/4.9.x/backward"
# ignoring nonexistent directory "/usr/aarch64-linux-android/bin/../sysroot/usr/local/include"
# ignoring nonexistent directory "/usr/aarch64-linux-android/bin/../sysroot/include"
# #include "..." search starts here:
# #include <...> search starts here:
# /work/deps/OpenBLAS
# /usr/aarch64-linux-android/bin/../lib/gcc/aarch64-linux-android/4.9.x/../../../.
# ./include/c++/4.9.x
# /usr/aarch64-linux-android/bin/../lib/gcc/aarch64-linux-android/4.9.x/../../../.
# ./include/c++/4.9.x/aarch64-linux-android
# /usr/aarch64-linux-android/lib64/clang/6.0.2/include
# /usr/aarch64-linux-android/bin/../sysroot/usr/include
# End of search list.
#
# The directory `/usr/include` is not in that list.
#
# As you can see, it is just easier to set the OpenBLAS_HOME variable.
popd
6 changes: 3 additions & 3 deletions cmake/ChooseBlas.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ if(USE_MKL_IF_AVAILABLE)
find_package(MKL)
endif()
if(MKL_FOUND)
if(USE_MKLDNN)
if(USE_MKLDNN)
set(BLAS "open")
else()
set(BLAS "MKL")
Expand All @@ -40,8 +40,8 @@ if(BLAS STREQUAL "Atlas" OR BLAS STREQUAL "atlas")
add_definitions(-DMXNET_USE_BLAS_ATLAS=1)
elseif(BLAS STREQUAL "Open" OR BLAS STREQUAL "open")
find_package(OpenBLAS REQUIRED)
include_directories(SYSTEM ${OpenBLAS_INCLUDE_DIR})
list(APPEND mshadow_LINKER_LIBS ${OpenBLAS_LIB})
include_directories(SYSTEM ${OpenBLAS_INCLUDE_DIRS})
list(APPEND mshadow_LINKER_LIBS ${OpenBLAS_LIBRARIES})
add_definitions(-DMSHADOW_USE_CBLAS=1)
add_definitions(-DMSHADOW_USE_MKL=0)
add_definitions(-DMXNET_USE_BLAS_OPEN=1)
Expand Down
249 changes: 176 additions & 73 deletions cmake/Modules/FindOpenBLAS.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -14,78 +14,181 @@
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
#
# Finds the OpenBLAS library.
#
# The following variables are set after configuration is done:
#
# - OpenBLAS_FOUND
# - OpenBLAS_INCLUDE_DIRS
# - OpenBLAS_LIBRARIES
#
# This script will try to find the OpenBLAS library using the following RESULT_VARs in this order:
#
# 1 - Use find_package(OpenBLAS) in Config mode.
# 2 - Find the files manually
#
# At each step that was just described, in order to guarantee that the library was found correctly,
# this script tries to compile this simple program:
#
# #include <cblas.h>
# int main() {
# cblas_sasum(0, (float*)0, 0);
# return 0;
# }
#
# If this simple program can't be compiled with the OpenBLAS library discovered in the previous
# step, then it assumes the step failed and moves on to the next step.
#
# To control where OpenBLAS should be searched for, one can set the environment variable
# `OpenBLAS_HOME` point to the installation directory of OpenBLAS:
#
# set OpenBLAS_HOME=c:\mxnet

include(CheckCSourceCompiles)
function(check_openblas_compiles RESULT_VAR)
message(STATUS "Testing a simple OpenBLAS program with: (${RESULT_VAR}, "
"includes: ${OpenBLAS_INCLUDE_DIRS}, "
"libs: ${OpenBLAS_LIBRARIES})")
set(CMAKE_REQUIRED_INCLUDES "${OpenBLAS_INCLUDE_DIRS}")
set(CMAKE_REQUIRED_LIBRARIES "${OpenBLAS_LIBRARIES}")

check_c_source_compiles("
#include <cblas.h>
int main() { cblas_sasum(0, (float*)0, 0); return 0; }
" OPENBLAS_CAN_COMPILE)

unset(CMAKE_REQUIRED_INCLUDES CACHE)
unset(CMAKE_REQUIRED_LIBRARIES CACHE)

if (NOT ${CAN_COMPILE})
message(WARNING "Couldn't compile a simple program to test for OpenBLAS presence using the '${RESULT_VAR}' RESULT_VAR. "
"To verify the error from the compiler, run cmake with the flag `--debug-trycompile`. "
"Check that the include directories are correct and contain the 'cblas.h' file: ${OpenBLAS_INCLUDE_DIRS} "
"Check that the library directory also contains the compiled library: '${OpenBLAS_LIBRARIES}'.")
else()
message(STATUS "Found OpenBLAS via ${RESULT_VAR} (include: ${OpenBLAS_INCLUDE_DIRS})")
message(STATUS "Found OpenBLAS via ${RESULT_VAR} (lib: ${OpenBLAS_LIBRARIES})")
endif()

set(${RESULT_VAR} ${OPENBLAS_CAN_COMPILE} PARENT_SCOPE)
unset(OPENBLAS_CAN_COMPILE CACHE)
endfunction()

macro(unset_openblas_variables)
unset(OpenBLAS_FOUND)
unset(OpenBLAS_FOUND CACHE)
unset(OpenBLAS_LIBRARIES)
unset(OpenBLAS_LIBRARIES CACHE)
unset(OpenBLAS_INCLUDE_DIRS)
unset(OpenBLAS_INCLUDE_DIRS CACHE)
endmacro()

# Try config-mode
find_package(OpenBLAS
NO_MODULE # Forcing Config mode, otherwise this would be an infinite loop.
PATHS $ENV{OpenBLAS_HOME}
)
if (OpenBLAS_FOUND)
check_openblas_compiles(OpenBLAS_CONFIG_MODE)
if (OpenBLAS_CONFIG_MODE)
return()
else()
unset_openblas_variables()
endif()
endif()

# Try finding the files manually
if(CMAKE_CROSSCOMPILING)
set(OpenBLAS_INCLUDE_SEARCH_PATHS
${OpenBLAS_INCLUDE_SEARCH_PATHS}

"$ENV{CROSS_ROOT}"
"${CROSS_ROOT}"
)
endif()

set(OpenBLAS_INCLUDE_SEARCH_PATHS
${OpenBLAS_INCLUDE_SEARCH_PATHS}

"$ENV{OpenBLAS_HOME}"
"${OpenBLAS_HOME}"
"${OpenBLAS_ROOT}"

/usr
/usr/include/openblas
/usr/include/openblas-base
/usr/local
/usr/local/include/openblas
/usr/local/include/openblas-base
/opt/OpenBLAS
/usr/local/opt/openblas

"${PROJECT_SOURCE_DIR}/3rdparty/OpenBLAS"
"${PROJECT_SOURCE_DIR}/thirdparty/OpenBLAS"
)

if(CMAKE_CROSSCOMPILING)
set(Open_BLAS_LIB_SEARCH_PATHS
${Open_BLAS_LIB_SEARCH_PATHS}

"$ENV{CROSS_ROOT}"
"${CROSS_ROOT}"
)
endif()

set(OpenBLAS_LIB_SEARCH_PATHS
${OpenBLAS_LIB_SEARCH_PATHS}

"$ENV{OpenBLAS_HOME}"
"${OpenBLAS_HOME}"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't need Openblas_home/include? Where is this list coming from?

"${OpenBLAS_ROOT}"

/
/lib/openblas-base
/usr
/usr/lib/openblas-base
/usr/local/
/opt/OpenBLAS
/usr/local/opt/openblas

"${PROJECT_SOURCE_DIR}/3rdparty/OpenBLAS"
"${PROJECT_SOURCE_DIR}/thirdparty/OpenBLAS"
)

find_path(OpenBLAS_INCLUDE_DIRS
NAMES cblas.h
PATHS ${OpenBLAS_INCLUDE_SEARCH_PATHS}
PATH_SUFFIXES include include/openblas)

set(OpenBLAS_LIB_NAMES openblas libopenblas)

if(CMAKE_CROSSCOMPILING)
message(STATUS "Will try to link to OpenBLAS statically")
set(OpenBLAS_LIB_NAMES libopenblas.a ${OpenBLAS_LIB_NAMES})
endif()

if(MSVC)
# The OpenBLAS distributed in SourceForge has this non-standard file extension: *.a
# From the README there, it shows:
# libopenblas.dll The shared library for Visual Studio and GCC.
# libopenblas.a The static library. Only work with GCC.
# libopenblas.dll.a The import library for Visual Studio.
# We have to use `libopenblas.dll.a` since this is the library file compiled for Visual
# Studio. This might not be ideal for Windows users since they will also need the DLL to be on
# their PATH, but that's how this distribution of OpenBLAS is.
list(APPEND CMAKE_FIND_LIBRARY_SUFFIXES .dll.a)
endif()

find_library(OpenBLAS_LIBRARIES
NAMES ${OpenBLAS_LIB_NAMES}
PATHS ${OpenBLAS_LIB_SEARCH_PATHS}
PATH_SUFFIXES lib lib64)

file(TO_CMAKE_PATH "$ENV{OpenBLAS_HOME}" OpenBLAS_HOME)
file(TO_CMAKE_PATH "$ENV{OpenBLAS}" OpenBLAS_DIR)

SET(Open_BLAS_INCLUDE_SEARCH_PATHS
/usr/include
/usr/include/openblas
/usr/include/openblas-base
/usr/local/include
/usr/local/include/openblas
/usr/local/include/openblas-base
/opt/OpenBLAS/include
/usr/local/opt/openblas/include
${PROJECT_SOURCE_DIR}/3rdparty/OpenBLAS/include
${PROJECT_SOURCE_DIR}/thirdparty/OpenBLAS/include
${OpenBLAS_HOME}
${OpenBLAS_HOME}/include
)

SET(Open_BLAS_LIB_SEARCH_PATHS
/lib/
/lib/openblas-base
/lib64/
/usr/lib
/usr/lib/openblas-base
/usr/lib64
/usr/local/lib
/usr/local/lib64
/opt/OpenBLAS/lib
/usr/local/opt/openblas/lib
${PROJECT_SOURCE_DIR}/3rdparty/OpenBLAS/lib
${PROJECT_SOURCE_DIR}/thirdparty/OpenBLAS/lib
${OpenBLAS_DIR}
${OpenBLAS_DIR}/lib
${OpenBLAS_HOME}
${OpenBLAS_HOME}/lib
)

FIND_PATH(OpenBLAS_INCLUDE_DIR NAMES cblas.h PATHS ${Open_BLAS_INCLUDE_SEARCH_PATHS})
FIND_LIBRARY(OpenBLAS_LIB NAMES openblas PATHS ${Open_BLAS_LIB_SEARCH_PATHS})
IF(NOT OpenBLAS_LIB)
FIND_FILE(OpenBLAS_LIB NAMES libopenblas.dll.a PATHS ${Open_BLAS_LIB_SEARCH_PATHS})
ENDIF()

SET(OpenBLAS_FOUND ON)

# Check include files
IF(NOT OpenBLAS_INCLUDE_DIR)
SET(OpenBLAS_FOUND OFF)
MESSAGE(STATUS "Could not find OpenBLAS include. Turning OpenBLAS_FOUND off")
ENDIF()

# Check libraries
IF(NOT OpenBLAS_LIB)
SET(OpenBLAS_FOUND OFF)
MESSAGE(STATUS "Could not find OpenBLAS lib. Turning OpenBLAS_FOUND off")
ENDIF()

IF (OpenBLAS_FOUND)
IF (NOT OpenBLAS_FIND_QUIETLY)
MESSAGE(STATUS "Found OpenBLAS libraries: ${OpenBLAS_LIB}")
MESSAGE(STATUS "Found OpenBLAS include: ${OpenBLAS_INCLUDE_DIR}")
ENDIF (NOT OpenBLAS_FIND_QUIETLY)
ELSE (OpenBLAS_FOUND)
IF (OpenBLAS_FIND_REQUIRED)
MESSAGE(FATAL_ERROR "Could not find OpenBLAS")
ENDIF (OpenBLAS_FIND_REQUIRED)
ENDIF (OpenBLAS_FOUND)

MARK_AS_ADVANCED(
OpenBLAS_INCLUDE_DIR
OpenBLAS_LIB
OpenBLAS
)
check_openblas_compiles(OpenBLAS_MANUAL_MODE)
if (NOT OpenBLAS_MANUAL_MODE)
unset_openblas_variables()
endif()

include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(OpenBLAS DEFAULT_MSG OpenBLAS_INCLUDE_DIRS OpenBLAS_LIBRARIES)