2
# This module finds an installed fortran library that implements the BLAS
3
# linear-algebra interface (see http://www.netlib.org/blas/).
4
# The list of libraries searched for is taken
5
# from the autoconf macro file, acx_blas.m4 (distributed at
6
# http://ac-archive.sourceforge.net/ac-archive/acx_blas.html).
8
# This module sets the following variables:
9
# BLAS_FOUND - set to true if a library implementing the BLAS interface is found.
10
# BLAS_INFO - name of the detected BLAS library.
11
# BLAS_F2C - set to true if following the f2c return convention
12
# BLAS_LIBRARIES - list of libraries to link against to use BLAS
13
# BLAS_INCLUDE_DIR - include directory
15
# Do nothing if BLAS was found before
23
SET(WITH_BLAS "" CACHE STRING "Blas type [accelerate/acml/atlas/blis/generic/goto/mkl/open/veclib]")
26
INCLUDE(CheckCSourceRuns)
27
INCLUDE(CheckFortranFunctionExists)
29
MACRO(Check_Fortran_Libraries LIBRARIES _prefix _name _flags _list)
30
# This macro checks for the existence of the combination of fortran libraries
31
# given by _list. If the combination is found, this macro checks (using the
32
# Check_Fortran_Function_Exists macro) whether can link against that library
33
# combination using the name of a routine given by _name using the linker
34
# flags given by _flags. If the combination of libraries is found and passes
35
# the link test, LIBRARIES is set to the list of complete library paths that
36
# have been found. Otherwise, LIBRARIES is set to NOTFOUND.
37
# N.B. _prefix is the prefix applied to the names of all cached variables that
38
# are generated internally and marked advanced by this macro.
41
foreach(_elem ${_list})
43
set(__list "${__list} - ${_elem}")
45
set(__list "${_elem}")
48
message(STATUS "Checking for [${__list}]")
50
set(_libraries_work TRUE)
53
foreach(_library ${_list})
54
set(_combined_name ${_combined_name}_${_library})
57
find_library(${_prefix}_${_library}_LIBRARY
63
find_library(${_prefix}_${_library}_LIBRARY
65
PATHS /usr/local/lib /usr/lib /usr/local/lib64 /usr/lib64 /opt/OpenBLAS/lib /usr/lib/aarch64-linux-gnu
66
ENV DYLD_LIBRARY_PATH )
68
find_library(${_prefix}_${_library}_LIBRARY
70
PATHS /usr/local/lib /usr/lib /usr/local/lib64 /usr/lib64 /opt/OpenBLAS/lib /usr/lib/aarch64-linux-gnu ${CMAKE_C_IMPLICIT_LINK_DIRECTORIES}
73
mark_as_advanced(${_prefix}_${_library}_LIBRARY)
74
set(${LIBRARIES} ${${LIBRARIES}} ${${_prefix}_${_library}_LIBRARY})
75
set(_libraries_work ${${_prefix}_${_library}_LIBRARY})
76
MESSAGE(STATUS " Library ${_library}: ${${_prefix}_${_library}_LIBRARY}")
77
endif(_libraries_work)
78
endforeach(_library ${_list})
80
# Test this combination of libraries.
81
set(CMAKE_REQUIRED_LIBRARIES ${_flags} ${${LIBRARIES}})
82
if (CMAKE_Fortran_COMPILER_WORKS)
83
check_fortran_function_exists(${_name} ${_prefix}${_combined_name}_WORKS)
84
else (CMAKE_Fortran_COMPILER_WORKS)
85
check_function_exists("${_name}_" ${_prefix}${_combined_name}_WORKS)
86
endif(CMAKE_Fortran_COMPILER_WORKS)
87
set(CMAKE_REQUIRED_LIBRARIES)
88
mark_as_advanced(${_prefix}${_combined_name}_WORKS)
89
set(_libraries_work ${${_prefix}${_combined_name}_WORKS})
90
endif(_libraries_work)
91
if(NOT _libraries_work)
92
set(${LIBRARIES} NOTFOUND)
93
endif(NOT _libraries_work)
94
endmacro(Check_Fortran_Libraries)
97
if((NOT BLAS_LIBRARIES)
98
AND ((NOT WITH_BLAS) OR (WITH_BLAS STREQUAL "mkl")))
102
SET(BLAS_LIBRARIES ${MKL_LIBRARIES})
103
SET(BLAS_INCLUDE_DIR ${MKL_INCLUDE_DIR})
104
SET(BLAS_VERSION ${MKL_VERSION})
109
if((NOT BLAS_LIBRARIES)
110
AND ((NOT WITH_BLAS) OR (WITH_BLAS STREQUAL "blis")))
111
check_fortran_libraries(
118
set(BLAS_INFO "blis")
119
endif(BLAS_LIBRARIES)
123
if((NOT BLAS_LIBRARIES)
124
AND ((NOT WITH_BLAS) OR (WITH_BLAS STREQUAL "accelerate")))
125
check_fortran_libraries(
132
set(BLAS_INFO "accelerate")
133
set(BLAS_IS_ACCELERATE 1)
134
endif(BLAS_LIBRARIES)
137
if((NOT BLAS_LIBRARIES)
138
AND ((NOT WITH_BLAS) OR (WITH_BLAS STREQUAL "veclib")))
141
SET(BLAS_INFO "veclib")
143
check_fortran_libraries(
150
set(BLAS_INFO "veclib")
151
endif(BLAS_LIBRARIES)
155
if((NOT BLAS_LIBRARIES)
156
AND ((NOT WITH_BLAS) OR (WITH_BLAS STREQUAL "flexi")))
157
check_fortran_libraries(
164
set(BLAS_INFO "flexi")
165
endif(BLAS_LIBRARIES)
168
if((NOT BLAS_LIBRARIES)
169
AND ((NOT WITH_BLAS) OR (WITH_BLAS STREQUAL "open")))
170
check_fortran_libraries(
177
set(BLAS_INFO "open")
178
endif(BLAS_LIBRARIES)
181
if((NOT BLAS_LIBRARIES)
182
AND ((NOT WITH_BLAS) OR (WITH_BLAS STREQUAL "open")))
183
check_fortran_libraries(
188
"openblas;pthread;m")
190
set(BLAS_INFO "open")
191
endif(BLAS_LIBRARIES)
194
if((NOT BLAS_LIBRARIES)
195
AND ((NOT WITH_BLAS) OR (WITH_BLAS STREQUAL "open")))
196
check_fortran_libraries(
201
"openblas;pthread;m;gomp")
203
set(BLAS_INFO "open")
204
endif(BLAS_LIBRARIES)
207
if((NOT BLAS_LIBRARIES) AND (WIN32)
208
AND ((NOT WITH_BLAS) OR (WITH_BLAS STREQUAL "open")))
209
check_fortran_libraries(
216
set(BLAS_INFO "open")
217
endif(BLAS_LIBRARIES)
220
if((NOT BLAS_LIBRARIES)
221
AND ((NOT WITH_BLAS) OR (WITH_BLAS STREQUAL "goto")))
222
check_fortran_libraries(
229
set(BLAS_INFO "goto")
230
endif(BLAS_LIBRARIES)
233
if((NOT BLAS_LIBRARIES)
234
AND ((NOT WITH_BLAS) OR (WITH_BLAS STREQUAL "goto")))
235
check_fortran_libraries(
240
"goto2;gfortran;pthread")
242
set(BLAS_INFO "goto")
243
endif(BLAS_LIBRARIES)
246
if((NOT BLAS_LIBRARIES)
247
AND ((NOT WITH_BLAS) OR (WITH_BLAS STREQUAL "acml")))
248
check_fortran_libraries(
255
set(BLAS_INFO "acml")
256
endif(BLAS_LIBRARIES)
259
if((NOT BLAS_LIBRARIES)
260
AND ((NOT WITH_BLAS) OR (WITH_BLAS STREQUAL "FLAME")))
261
# FLAME's blis library (https://github.com/flame/blis)
262
check_fortran_libraries(
269
set(BLAS_INFO "FLAME")
270
endif(BLAS_LIBRARIES)
273
# BLAS in ATLAS library? (http://math-atlas.sourceforge.net/)
274
if((NOT BLAS_LIBRARIES)
275
AND ((NOT WITH_BLAS) OR (WITH_BLAS STREQUAL "atlas")))
278
SET(BLAS_INFO "atlas")
280
check_fortran_libraries(
285
"ptf77blas;atlas;gfortran")
287
set(BLAS_INFO "atlas")
288
endif(BLAS_LIBRARIES)
292
# Generic BLAS library?
293
if((NOT BLAS_LIBRARIES)
294
AND ((NOT WITH_BLAS) OR (WITH_BLAS STREQUAL "generic")))
295
if(ENV{GENERIC_BLAS_LIBRARIES} STREQUAL "")
296
set(GENERIC_BLAS "blas")
298
set(GENERIC_BLAS $ENV{GENERIC_BLAS_LIBRARIES})
300
check_fortran_libraries(
307
set(BLAS_INFO "generic")
308
endif(BLAS_LIBRARIES)
311
# Determine if blas was compiled with the f2c conventions
313
# Push host architecture when cross-compiling otherwise check would fail
314
# when cross-compiling for arm64 on x86_64
315
cmake_push_check_state(RESET)
316
if(CMAKE_SYSTEM_NAME STREQUAL "Darwin" AND CMAKE_OSX_ARCHITECTURES MATCHES "^(x86_64|arm64)$")
317
list(APPEND CMAKE_REQUIRED_FLAGS "-arch ${CMAKE_HOST_SYSTEM_PROCESSOR}")
320
# Set values through env variables if cross compiling
321
IF (CMAKE_CROSSCOMPILING)
322
IF("$ENV{PYTORCH_BLAS_F2C}" STREQUAL "ON")
328
IF("$ENV{PYTORCH_BLAS_USE_CBLAS_DOT}" STREQUAL "ON")
329
SET(BLAS_USE_CBLAS_DOT TRUE)
331
SET(BLAS_USE_CBLAS_DOT FALSE)
334
SET(CMAKE_REQUIRED_LIBRARIES ${BLAS_LIBRARIES})
335
CHECK_C_SOURCE_RUNS("
338
float x[4] = { 1, 2, 3, 4 };
339
float y[4] = { .1, .01, .001, .0001 };
342
extern double sdot_();
345
double r = sdot_(&four, x, &one, y, &one);
346
exit((float)r != (float).1234);
347
}" BLAS_F2C_DOUBLE_WORKS )
348
CHECK_C_SOURCE_RUNS("
351
float x[4] = { 1, 2, 3, 4 };
352
float y[4] = { .1, .01, .001, .0001 };
355
extern float sdot_();
358
double r = sdot_(&four, x, &one, y, &one);
359
exit((float)r != (float).1234);
360
}" BLAS_F2C_FLOAT_WORKS )
361
IF (BLAS_F2C_DOUBLE_WORKS AND NOT BLAS_F2C_FLOAT_WORKS)
362
MESSAGE(STATUS "This BLAS uses the F2C return conventions")
364
ELSE (BLAS_F2C_DOUBLE_WORKS AND NOT BLAS_F2C_FLOAT_WORKS)
366
ENDIF(BLAS_F2C_DOUBLE_WORKS AND NOT BLAS_F2C_FLOAT_WORKS)
367
CHECK_C_SOURCE_RUNS("
370
float x[4] = { 1, 2, 3, 4 };
371
float y[4] = { .1, .01, .001, .0001 };
372
extern float cblas_sdot();
375
double r = cblas_sdot(4, x, 1, y, 1);
376
exit((float)r != (float).1234);
377
}" BLAS_USE_CBLAS_DOT )
378
IF (BLAS_USE_CBLAS_DOT)
379
SET(BLAS_USE_CBLAS_DOT TRUE)
380
ELSE (BLAS_USE_CBLAS_DOT)
381
SET(BLAS_USE_CBLAS_DOT FALSE)
382
ENDIF(BLAS_USE_CBLAS_DOT)
383
SET(CMAKE_REQUIRED_LIBRARIES)
384
ENDIF(CMAKE_CROSSCOMPILING)
385
cmake_pop_check_state()
393
set(BLAS_FOUND FALSE)
396
IF (NOT BLAS_FOUND AND BLAS_FIND_REQUIRED)
397
message(FATAL_ERROR "Cannot find a library with BLAS API. Please specify library location.")
398
ENDIF(NOT BLAS_FOUND AND BLAS_FIND_REQUIRED)
399
IF(NOT BLAS_FIND_QUIETLY)
401
MESSAGE(STATUS "Found a library with BLAS API (${BLAS_INFO}). Full path: (${BLAS_LIBRARIES})")
403
MESSAGE(STATUS "Cannot find a library with BLAS API. Not using BLAS.")
405
ENDIF(NOT BLAS_FIND_QUIETLY)
407
# Do nothing is BLAS was found before
410
# Blas has bfloat16 support?
412
INCLUDE(CheckFunctionExists)
413
SET(CMAKE_REQUIRED_LIBRARIES ${BLAS_LIBRARIES})
414
check_function_exists("sbgemm_" BLAS_HAS_SBGEMM)
415
set(CMAKE_REQUIRED_LIBRARIES)
417
add_compile_options(-DBLAS_HAS_SBGEMM)
418
ENDIF(BLAS_HAS_SBGEMM)