diff --git a/Readme_LAPACK.md b/Readme_LAPACK.md index bd831fa..f1d934c 100644 --- a/Readme_LAPACK.md +++ b/Readme_LAPACK.md @@ -1,9 +1,9 @@ -# LAPACK options +# LAPACK / ScaLAPACK options -The underlying "LAPACK" linear algebra interface is available from several vendors. +The underlying "LAPACK" and ScaLAPACK linear algebra interfacs are available from several vendors. By default, the generic LAPACK library "lapack" is searched for. -To specify a particular LAPACK library, use CMake configure variable "LAPACK_VENDOR" using one of the following vendors: +To specify a particular LAPACK library, use CMake configure variable "LAPACK_VENDOR" and "SCALAPACK_VENDOR" using one of the following vendors: * AOCL [AMD Optimizing CPU Libraries](https://www.amd.com/en/developer/aocl.html) * Atlas [Automatically Tuned Linear Algebra Software](http://math-atlas.sourceforge.net/) @@ -17,6 +17,12 @@ For example, to use OpenBLAS: cmake -DLAPACK_VENDOR=OpenBLAS ``` +To use AMD AOCL: + +```sh +cmake -DLAPACK_VENDOR=AOCL +``` + Optionally, hint the location the LAPACK library like: ```sh diff --git a/cmake/FindLAPACK.cmake b/cmake/FindLAPACK.cmake index a633d6c..56dde6f 100644 --- a/cmake/FindLAPACK.cmake +++ b/cmake/FindLAPACK.cmake @@ -43,10 +43,15 @@ COMPONENTS default to Netlib LAPACK / LapackE, otherwise: ``AOCL`` - AMD Optimizing CPU Libraries + AMD ScaLAPACK fork of Netlib ScaLAPACK. + Requires LAPACK AOCL + https://www.amd.com/en/developer/aocl/scalapack.html +``AOCL64`` + AOCL 64-bit integers (default is 32-bit integers) ``LAPACKE`` - Netlib LapackE for C / C++ + LapackE C / C++ interface + ``Netlib`` Netlib Lapack for Fortran ``OpenBLAS`` @@ -83,7 +88,7 @@ References * MKL LAPACKE (C, C++): https://software.intel.com/en-us/mkl-linux-developer-guide-calling-lapack-blas-and-cblas-routines-from-c-c-language-environments #]=======================================================================] -include(CheckFortranSourceCompiles) +include(CheckSourceCompiles) # clear to avoid endless appending on subsequent calls set(LAPACK_LIBRARY) @@ -91,7 +96,7 @@ unset(LAPACK_INCLUDE_DIR) # ===== functions ========== -function(atlas_libs) +function(lapack_atlas) find_library(ATLAS_LIB NAMES atlas @@ -135,11 +140,11 @@ endif() set(LAPACK_LIBRARY ${LAPACK_LIBRARY} PARENT_SCOPE) -endfunction(atlas_libs) +endfunction() #======================= -function(netlib_libs) +function(lapack_netlib) if(LAPACK95 IN_LIST LAPACK_FIND_COMPONENTS) find_path(LAPACK95_INCLUDE_DIR @@ -216,10 +221,10 @@ list(APPEND LAPACK_LIBRARY ${CMAKE_THREAD_LIBS_INIT}) set(LAPACK_LIBRARY ${LAPACK_LIBRARY} PARENT_SCOPE) -endfunction(netlib_libs) +endfunction() #=============================== -function(openblas_libs) +function(lapack_openblas) find_library(LAPACK_LIBRARY NAMES openblas @@ -244,10 +249,15 @@ list(APPEND LAPACK_LIBRARY ${CMAKE_THREAD_LIBS_INIT}) set(LAPACK_LIBRARY ${LAPACK_LIBRARY} PARENT_SCOPE) -endfunction(openblas_libs) +endfunction() + +function(lapack_aocl) -function(aocl_libs) +set(_nodef_lapack) +if(DEFINED LAPACK_ROOT) + set(_nodef_lapack NO_DEFAULT_PATH) +endif() set(_names flame) if(WIN32) @@ -258,13 +268,38 @@ if(WIN32) endif() endif() +set(_s "LP64") +if(AOCL64 IN_LIST SCALAPACK_FIND_COMPONENTS) + string(PREPEND _s "I") +endif() + find_library(LAPACK_LIBRARY NAMES ${_names} NAMES_PER_DIR -PATH_SUFFIXES LP64 -DOC "LAPACK Flame library" +PATH_SUFFIXES lib/${_s} +HINTS ${LAPACK_ROOT} $ENV{LAPACK_ROOT} +${_nodef_lapack} +DOC "AOCL Flame library" ) +find_path(LAPACK_INCLUDE_DIR +NAMES FLAME.h +PATH_SUFFIXES include/${_s} +HINTS ${LAPACK_ROOT} $ENV{LAPACK_ROOT} +${_nodef_lapack} +DOC "Flame header" +) + +if(NOT LAPACK_LIBRARY AND LAPACK_INCLUDE_DIR) + return() +endif() + +# --- BLIS +set(_nodef_blas) +if(DEFINED BLAS_ROOT) + set(_nodef_blas NO_DEFAULT_PATH) +endif() + set(_names blis-mt blis) if(WIN32) if(BUILD_SHARED_LIBS) @@ -277,36 +312,61 @@ endif() find_library(BLAS_LIBRARY NAMES ${_names} NAMES_PER_DIR -PATH_SUFFIXES LP64 -DOC "BLAS Blis library" -) - -if(NOT (LAPACK_LIBRARY AND BLAS_LIBRARY)) - return() -endif() - -find_path(LAPACK_INCLUDE_DIR -NAMES FLAME.h -PATH_SUFFIXES LP64 -DOC "Flame header" +HINTS ${BLAS_ROOT} +PATH_SUFFIXES lib/${_s} +HINTS ${BLAS_ROOT} $ENV{BLAS_ROOT} +${_nodef_blas} +DOC "AOCL Blis library" ) find_path(BLAS_INCLUDE_DIR NAMES blis.h -PATH_SUFFIXES LP64 +HINTS ${BLAS_ROOT} +PATH_SUFFIXES include/${_s} +HINTS ${BLAS_ROOT} $ENV{BLAS_ROOT} +${_nodef_blas} DOC "Blis header" ) -if(NOT (LAPACK_INCLUDE_DIR AND BLAS_INCLUDE_DIR)) +if(NOT BLAS_LIBRARY AND BLAS_INCLUDE_DIR) return() endif() +if(LAPACKE IN_LIST LAPACK_FIND_COMPONENTS) + + find_library(LAPACKE_LIBRARY + NAMES lapacke + PATH_SUFFIXES lib/${_s} + HINTS ${LAPACK_ROOT} $ENV{LAPACK_ROOT} + ${_nodef_lapack} + DOC "AOCL LAPACKE library" + ) + + # lapack/include for Homebrew + find_path(LAPACKE_INCLUDE_DIR + NAMES lapacke.h + PATH_SUFFIXES include/${_s} + HINTS ${LAPACK_ROOT} $ENV{LAPACK_ROOT} + ${_nodef_lapack} + DOC "AOCL LAPACKE include directory" + ) + if(NOT (LAPACKE_LIBRARY AND LAPACKE_INCLUDE_DIR)) + return() + endif() + + set(LAPACK_LAPACKE_FOUND true PARENT_SCOPE) + list(APPEND LAPACK_INCLUDE_DIR ${LAPACKE_INCLUDE_DIR}) + list(APPEND LAPACK_LIBRARY ${LAPACKE_LIBRARY}) + mark_as_advanced(LAPACKE_LIBRARY LAPACKE_INCLUDE_DIR) +endif() + + set(LAPACK_AOCL_FOUND true PARENT_SCOPE) set(LAPACK_LIBRARY ${LAPACK_LIBRARY} ${BLAS_LIBRARY} ${CMAKE_THREAD_LIBS_INIT} PARENT_SCOPE) set(LAPACK_INCLUDE_DIR ${LAPACK_INCLUDE_DIR} ${BLAS_INCLUDE_DIR} PARENT_SCOPE) -endfunction(aocl_libs) +endfunction() #=============================== @@ -393,13 +453,13 @@ endif() if(MKL IN_LIST LAPACK_FIND_COMPONENTS OR MKL64 IN_LIST LAPACK_FIND_COMPONENTS) lapack_mkl() elseif(Atlas IN_LIST LAPACK_FIND_COMPONENTS) - atlas_libs() + lapack_atlas() elseif(Netlib IN_LIST LAPACK_FIND_COMPONENTS) - netlib_libs() + lapack_netlib() elseif(OpenBLAS IN_LIST LAPACK_FIND_COMPONENTS) - openblas_libs() + lapack_openblas() elseif(AOCL IN_LIST LAPACK_FIND_COMPONENTS) - aocl_libs() + lapack_aocl() elseif(LAPACK_CRAY) # LAPACK is implicitly part of Cray PE LibSci, use Cray compiler wrapper. endif() @@ -426,7 +486,7 @@ set(CMAKE_REQUIRED_LINK_OPTIONS) set(CMAKE_REQUIRED_INCLUDES ${LAPACK_INCLUDE_DIR}) set(CMAKE_REQUIRED_LIBRARIES ${LAPACK_LIBRARY}) -check_fortran_source_compiles( +check_source_compiles(Fortran "program check_lapack use, intrinsic :: iso_fortran_env, only : real32 implicit none @@ -434,10 +494,9 @@ real(real32), external :: snrm2 print *, snrm2(1, [0._real32], 1) end program" LAPACK_s_FOUND -SRC_EXT f90 ) -check_fortran_source_compiles( +check_source_compiles(Fortran "program check_lapack use, intrinsic :: iso_fortran_env, only : real64 implicit none @@ -445,14 +504,13 @@ real(real64), external :: dnrm2 print *, dnrm2(1, [0._real64], 1) end program" LAPACK_d_FOUND -SRC_EXT f90 ) if(LAPACK_s_FOUND OR LAPACK_d_FOUND) set(LAPACK_links true PARENT_SCOPE) endif() -endfunction(lapack_check) +endfunction() # --- Check library links if(LAPACK_CRAY OR LAPACK_LIBRARY) diff --git a/cmake/FindSCALAPACK.cmake b/cmake/FindSCALAPACK.cmake index 0e65507..d1880b7 100644 --- a/cmake/FindSCALAPACK.cmake +++ b/cmake/FindSCALAPACK.cmake @@ -20,16 +20,20 @@ COMPONENTS ``MKL`` Intel MKL for MSVC, oneAPI, GCC. Working with IntelMPI (default Window, Linux), MPICH (default Mac) or OpenMPI (Linux only). - ``MKL64`` - MKL only: 64-bit integers (default is 32-bit integers) - + MKL 64-bit integers (default is 32-bit integers) ``TBB`` - Intel MPI + TBB for MKL (default is sequential) - + MKL only: Intel MPI + TBB (default is sequential) ``OpenMP`` MKL only: use OpenMP (default is sequential) +``AOCL`` + AMD ScaLAPACK fork of Netlib ScaLAPACK. + Requires LAPACK AOCL + https://www.amd.com/en/developer/aocl/scalapack.html +``AOCL64`` + AOCL 64-bit integers (default is 32-bit integers) + ``STATIC`` Library search default on non-Windows is shared then static. On Windows default search is static only. Specifying STATIC component searches for static libraries only. @@ -56,7 +60,7 @@ References * MKL link-line advisor: https://software.intel.com/en-us/articles/intel-mkl-link-line-advisor #]=======================================================================] -include(CheckFortranSourceCompiles) +include(CheckSourceCompiles) set(SCALAPACK_LIBRARY) # avoids appending to prior FindScalapack @@ -86,7 +90,7 @@ if(STATIC IN_LIST SCALAPACK_FIND_COMPONENTS AND endif() # MPI needed for IntelLLVM -check_fortran_source_compiles( +check_source_compiles(Fortran "program test use, intrinsic :: iso_fortran_env, only : real64 implicit none @@ -95,10 +99,9 @@ integer :: ictxt print *, pdlamch(ictxt, 'E') end program" SCALAPACK_d_FOUND -SRC_EXT f90 ) -check_fortran_source_compiles( +check_source_compiles(Fortran "program test use, intrinsic :: iso_fortran_env, only : real32 implicit none @@ -107,14 +110,13 @@ integer :: ictxt print *, pslamch(ictxt, 'E') end program" SCALAPACK_s_FOUND -SRC_EXT f90 ) if(SCALAPACK_s_FOUND OR SCALAPACK_d_FOUND) set(SCALAPACK_links true PARENT_SCOPE) endif() -endfunction(scalapack_check) +endfunction() macro(scalapack_mkl) @@ -167,8 +169,37 @@ endforeach() endmacro() +#========================== + +function(scalapack_aocl) + +set(_nodef_scalapack) +if(DEFINED SCALAPACK_ROOT) + set(_nodef_scalapack NO_DEFAULT_PATH) +endif() + +set(_s "LP64") +if(AOCL64 IN_LIST SCALAPACK_FIND_COMPONENTS) + string(PREPEND _s "I") +endif() + +find_library(SCALAPACK_LIBRARY +NAMES scalapack +PATH_SUFFIXES lib/${_s} +HINTS ${SCALAPACK_ROOT} $ENV{SCALAPACK_ROOT} +${_nodef_scalapack} +DOC "AOCL SCALAPACK library" +) + +if(SCALAPACK_LIBRARY) + set(SCALAPACK_AOCL_FOUND true PARENT_SCOPE) +endif() + +endfunction() + +#=========================== -function(scalapack_lib) +function(scalapack_netlib) if(BUILD_SHARED_LIBS) set(_s shared) @@ -196,7 +227,7 @@ HINTS ${BLACS_ROOT} DOC "BLACS library" ) -endfunction(scalapack_lib) +endfunction() # === main @@ -219,8 +250,10 @@ if(MKL IN_LIST SCALAPACK_FIND_COMPONENTS OR MKL64 IN_LIST SCALAPACK_FIND_COMPONE scalapack_mkl() elseif(SCALAPACK_CRAY) # Cray PE has Scalapack build into LibSci. Use Cray compiler wrapper. +elseif(AOCL IN_LIST LAPACK_FIND_COMPONENTS) + scalapack_aocl() else() - scalapack_lib() + scalapack_netlib() endif() if(STATIC IN_LIST SCALAPACK_FIND_COMPONENTS) diff --git a/cmake/compilers.cmake b/cmake/compilers.cmake index c3b9315..1c46abf 100644 --- a/cmake/compilers.cmake +++ b/cmake/compilers.cmake @@ -23,7 +23,7 @@ add_compile_options( ) # IntelLLVM does not have -fno-strict-aliasing for Fortran -# this oneAPI flag needs to be applied EVERYWHERE incl. submodule projects +# the Intel oneAPI fpscomp flag needs to be applied EVERYWHERE incl. submodule projects # or runtime errors / weird behavior with unresolved procedures that actually exist. # -standard-semantics is no good because it breaks linkage within oneAPI itself e.g. oneMPI library! add_compile_options("$<$:$,/fpscomp:logicals,-fpscomp;logicals>>") diff --git a/cmake/scalapack.cmake b/cmake/scalapack.cmake index 018fc1d..8727508 100644 --- a/cmake/scalapack.cmake +++ b/cmake/scalapack.cmake @@ -3,6 +3,8 @@ include(GNUInstallDirs) if(find AND NOT TARGET SCALAPACK::SCALAPACK) +# Make SCALAPACK_VENDOR match LAPACK_VENDOR + if(NOT DEFINED SCALAPACK_VENDOR) if(LAPACK_VENDOR MATCHES "^MKL") set(SCALAPACK_VENDOR MKL) @@ -11,6 +13,10 @@ if(NOT DEFINED SCALAPACK_VENDOR) set(SCALAPACK_VENDOR MKL) set(LAPACK_VENDOR MKL) endif() + + if(LAPACK_VENDOR STREQUAL "AOCL") + set(SCALAPACK_VENDOR AOCL) + endif() endif() if(MKL IN_LIST SCALAPACK_VENDOR) @@ -35,6 +41,8 @@ endif() if(SCALAPACK_FOUND OR TARGET SCALAPACK::SCALAPACK) return() +elseif(DEFINED SCALAPACK_VENDOR) + message(FATAL_ERROR "Scalapack from ${SCALAPACK_VENDOR} not found.") endif() set(scalapack_cmake_args