xref: /aosp_15_r20/external/pytorch/cmake/Modules/FindBLAS.cmake (revision da0073e96a02ea20f0ac840b70461e3646d07c45)
1# - Find BLAS library
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).
7#
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
14
15# Do nothing if BLAS was found before
16IF(NOT BLAS_FOUND)
17
18SET(BLAS_LIBRARIES)
19SET(BLAS_INCLUDE_DIR)
20SET(BLAS_INFO)
21SET(BLAS_F2C)
22
23SET(WITH_BLAS "" CACHE STRING "Blas type [accelerate/acml/atlas/blis/generic/goto/mkl/open/veclib]")
24
25# Old FindBlas
26INCLUDE(CheckCSourceRuns)
27INCLUDE(CheckFortranFunctionExists)
28
29MACRO(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.
39
40  set(__list)
41  foreach(_elem ${_list})
42    if(__list)
43      set(__list "${__list} - ${_elem}")
44    else(__list)
45      set(__list "${_elem}")
46    endif(__list)
47  endforeach(_elem)
48  message(STATUS "Checking for [${__list}]")
49
50  set(_libraries_work TRUE)
51  set(${LIBRARIES})
52  set(_combined_name)
53  foreach(_library ${_list})
54    set(_combined_name ${_combined_name}_${_library})
55    if(_libraries_work)
56      if ( WIN32 )
57        find_library(${_prefix}_${_library}_LIBRARY
58          NAMES ${_library}
59          PATHS ENV LIB
60          PATHS ENV PATH )
61      endif ( WIN32 )
62      if ( APPLE )
63        find_library(${_prefix}_${_library}_LIBRARY
64          NAMES ${_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 )
67      else ( APPLE )
68        find_library(${_prefix}_${_library}_LIBRARY
69          NAMES ${_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}
71          ENV LD_LIBRARY_PATH )
72      endif( APPLE )
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})
79  if(_libraries_work)
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)
94endmacro(Check_Fortran_Libraries)
95
96# Intel MKL?
97if((NOT BLAS_LIBRARIES)
98    AND ((NOT WITH_BLAS) OR (WITH_BLAS STREQUAL "mkl")))
99  FIND_PACKAGE(MKL)
100  IF(MKL_FOUND)
101    SET(BLAS_INFO "mkl")
102    SET(BLAS_LIBRARIES ${MKL_LIBRARIES})
103    SET(BLAS_INCLUDE_DIR ${MKL_INCLUDE_DIR})
104    SET(BLAS_VERSION ${MKL_VERSION})
105  ENDIF(MKL_FOUND)
106endif()
107
108#BLIS?
109if((NOT BLAS_LIBRARIES)
110    AND ((NOT WITH_BLAS) OR (WITH_BLAS STREQUAL "blis")))
111  check_fortran_libraries(
112  BLAS_LIBRARIES
113  BLAS
114  sgemm
115  ""
116  "blis")
117  if(BLAS_LIBRARIES)
118    set(BLAS_INFO "blis")
119  endif(BLAS_LIBRARIES)
120endif()
121
122# Apple BLAS library?
123if((NOT BLAS_LIBRARIES)
124    AND ((NOT WITH_BLAS) OR (WITH_BLAS STREQUAL "accelerate")))
125  check_fortran_libraries(
126  BLAS_LIBRARIES
127  BLAS
128  sgemm
129  ""
130  "Accelerate")
131  if (BLAS_LIBRARIES)
132    set(BLAS_INFO "accelerate")
133    set(BLAS_IS_ACCELERATE 1)
134  endif(BLAS_LIBRARIES)
135endif()
136
137if((NOT BLAS_LIBRARIES)
138    AND ((NOT WITH_BLAS) OR (WITH_BLAS STREQUAL "veclib")))
139  FIND_PACKAGE(vecLib)
140  if(vecLib_FOUND)
141    SET(BLAS_INFO "veclib")
142  else()
143    check_fortran_libraries(
144      BLAS_LIBRARIES
145      BLAS
146      sgemm
147      ""
148      "vecLib")
149    if (BLAS_LIBRARIES)
150      set(BLAS_INFO "veclib")
151    endif(BLAS_LIBRARIES)
152  endif()
153endif()
154
155if((NOT BLAS_LIBRARIES)
156    AND ((NOT WITH_BLAS) OR (WITH_BLAS STREQUAL "flexi")))
157  check_fortran_libraries(
158  BLAS_LIBRARIES
159  BLAS
160  sgemm
161  ""
162  "flexiblas")
163  if(BLAS_LIBRARIES)
164    set(BLAS_INFO "flexi")
165  endif(BLAS_LIBRARIES)
166endif()
167
168if((NOT BLAS_LIBRARIES)
169    AND ((NOT WITH_BLAS) OR (WITH_BLAS STREQUAL "open")))
170  check_fortran_libraries(
171  BLAS_LIBRARIES
172  BLAS
173  sgemm
174  ""
175  "openblas")
176  if(BLAS_LIBRARIES)
177    set(BLAS_INFO "open")
178  endif(BLAS_LIBRARIES)
179endif()
180
181if((NOT BLAS_LIBRARIES)
182    AND ((NOT WITH_BLAS) OR (WITH_BLAS STREQUAL "open")))
183  check_fortran_libraries(
184  BLAS_LIBRARIES
185  BLAS
186  sgemm
187  ""
188  "openblas;pthread;m")
189  if(BLAS_LIBRARIES)
190    set(BLAS_INFO "open")
191  endif(BLAS_LIBRARIES)
192endif()
193
194if((NOT BLAS_LIBRARIES)
195    AND ((NOT WITH_BLAS) OR (WITH_BLAS STREQUAL "open")))
196  check_fortran_libraries(
197  BLAS_LIBRARIES
198  BLAS
199  sgemm
200  ""
201  "openblas;pthread;m;gomp")
202  if(BLAS_LIBRARIES)
203    set(BLAS_INFO "open")
204  endif(BLAS_LIBRARIES)
205endif()
206
207if((NOT BLAS_LIBRARIES) AND (WIN32)
208    AND ((NOT WITH_BLAS) OR (WITH_BLAS STREQUAL "open")))
209  check_fortran_libraries(
210  BLAS_LIBRARIES
211  BLAS
212  sgemm
213  ""
214  "libopenblas")
215  if(BLAS_LIBRARIES)
216    set(BLAS_INFO "open")
217  endif(BLAS_LIBRARIES)
218endif()
219
220if((NOT BLAS_LIBRARIES)
221    AND ((NOT WITH_BLAS) OR (WITH_BLAS STREQUAL "goto")))
222  check_fortran_libraries(
223  BLAS_LIBRARIES
224  BLAS
225  sgemm
226  ""
227  "goto2;gfortran")
228  if (BLAS_LIBRARIES)
229    set(BLAS_INFO "goto")
230  endif(BLAS_LIBRARIES)
231endif()
232
233if((NOT BLAS_LIBRARIES)
234    AND ((NOT WITH_BLAS) OR (WITH_BLAS STREQUAL "goto")))
235  check_fortran_libraries(
236  BLAS_LIBRARIES
237  BLAS
238  sgemm
239  ""
240  "goto2;gfortran;pthread")
241  if (BLAS_LIBRARIES)
242    set(BLAS_INFO "goto")
243  endif(BLAS_LIBRARIES)
244endif()
245
246if((NOT BLAS_LIBRARIES)
247    AND ((NOT WITH_BLAS) OR (WITH_BLAS STREQUAL "acml")))
248  check_fortran_libraries(
249  BLAS_LIBRARIES
250  BLAS
251  sgemm
252  ""
253  "acml;gfortran")
254  if (BLAS_LIBRARIES)
255    set(BLAS_INFO "acml")
256  endif(BLAS_LIBRARIES)
257endif()
258
259if((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(
263  BLAS_LIBRARIES
264  BLAS
265  sgemm
266  ""
267  "blis")
268  if (BLAS_LIBRARIES)
269    set(BLAS_INFO "FLAME")
270  endif(BLAS_LIBRARIES)
271endif()
272
273# BLAS in ATLAS library? (http://math-atlas.sourceforge.net/)
274if((NOT BLAS_LIBRARIES)
275    AND ((NOT WITH_BLAS) OR (WITH_BLAS STREQUAL "atlas")))
276  FIND_PACKAGE(Atlas)
277  if(Atlas_FOUND)
278    SET(BLAS_INFO "atlas")
279  else()
280    check_fortran_libraries(
281      BLAS_LIBRARIES
282      BLAS
283      sgemm
284      ""
285      "ptf77blas;atlas;gfortran")
286    if (BLAS_LIBRARIES)
287      set(BLAS_INFO "atlas")
288    endif(BLAS_LIBRARIES)
289  endif()
290endif()
291
292# Generic BLAS library?
293if((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")
297  else()
298    set(GENERIC_BLAS $ENV{GENERIC_BLAS_LIBRARIES})
299  endif()
300  check_fortran_libraries(
301  BLAS_LIBRARIES
302  BLAS
303  sgemm
304  ""
305  "${GENERIC_BLAS}")
306  if (BLAS_LIBRARIES)
307    set(BLAS_INFO "generic")
308  endif(BLAS_LIBRARIES)
309endif()
310
311# Determine if blas was compiled with the f2c conventions
312IF (BLAS_LIBRARIES)
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}")
318  endif()
319
320# Set values through env variables if cross compiling
321  IF (CMAKE_CROSSCOMPILING)
322    IF("$ENV{PYTORCH_BLAS_F2C}" STREQUAL "ON")
323      SET(BLAS_F2C TRUE)
324    ELSE()
325      SET(BLAS_F2C FALSE)
326    ENDIF()
327
328    IF("$ENV{PYTORCH_BLAS_USE_CBLAS_DOT}" STREQUAL "ON")
329      SET(BLAS_USE_CBLAS_DOT TRUE)
330    ELSE()
331      SET(BLAS_USE_CBLAS_DOT FALSE)
332    ENDIF()
333  ELSE ()
334    SET(CMAKE_REQUIRED_LIBRARIES ${BLAS_LIBRARIES})
335    CHECK_C_SOURCE_RUNS("
336  #include <stdlib.h>
337  #include <stdio.h>
338  float x[4] = { 1, 2, 3, 4 };
339  float y[4] = { .1, .01, .001, .0001 };
340  int four = 4;
341  int one = 1;
342  extern double sdot_();
343  int main() {
344    int i;
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("
349  #include <stdlib.h>
350  #include <stdio.h>
351  float x[4] = { 1, 2, 3, 4 };
352  float y[4] = { .1, .01, .001, .0001 };
353  int four = 4;
354  int one = 1;
355  extern float sdot_();
356  int main() {
357    int i;
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")
363      SET(BLAS_F2C TRUE)
364    ELSE (BLAS_F2C_DOUBLE_WORKS AND NOT BLAS_F2C_FLOAT_WORKS)
365      SET(BLAS_F2C FALSE)
366    ENDIF(BLAS_F2C_DOUBLE_WORKS AND NOT BLAS_F2C_FLOAT_WORKS)
367    CHECK_C_SOURCE_RUNS("
368  #include <stdlib.h>
369  #include <stdio.h>
370  float x[4] = { 1, 2, 3, 4 };
371  float y[4] = { .1, .01, .001, .0001 };
372  extern float cblas_sdot();
373  int main() {
374    int i;
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()
386ENDIF(BLAS_LIBRARIES)
387
388# epilogue
389
390if(BLAS_LIBRARIES)
391  set(BLAS_FOUND TRUE)
392else(BLAS_LIBRARIES)
393  set(BLAS_FOUND FALSE)
394endif(BLAS_LIBRARIES)
395
396IF (NOT BLAS_FOUND AND BLAS_FIND_REQUIRED)
397  message(FATAL_ERROR "Cannot find a library with BLAS API. Please specify library location.")
398ENDIF(NOT BLAS_FOUND AND BLAS_FIND_REQUIRED)
399IF(NOT BLAS_FIND_QUIETLY)
400  IF(BLAS_FOUND)
401    MESSAGE(STATUS "Found a library with BLAS API (${BLAS_INFO}). Full path: (${BLAS_LIBRARIES})")
402  ELSE(BLAS_FOUND)
403    MESSAGE(STATUS "Cannot find a library with BLAS API. Not using BLAS.")
404  ENDIF(BLAS_FOUND)
405ENDIF(NOT BLAS_FIND_QUIETLY)
406
407# Do nothing is BLAS was found before
408ENDIF(NOT BLAS_FOUND)
409
410# Blas has bfloat16 support?
411IF(BLAS_LIBRARIES)
412  INCLUDE(CheckFunctionExists)
413  SET(CMAKE_REQUIRED_LIBRARIES ${BLAS_LIBRARIES})
414  check_function_exists("sbgemm_" BLAS_HAS_SBGEMM)
415  set(CMAKE_REQUIRED_LIBRARIES)
416  IF(BLAS_HAS_SBGEMM)
417    add_compile_options(-DBLAS_HAS_SBGEMM)
418  ENDIF(BLAS_HAS_SBGEMM)
419ENDIF(BLAS_LIBRARIES)
420