From 74a7ee707c7ec52006befbb0071dea74c0e393b5 Mon Sep 17 00:00:00 2001 From: Ralf Gommers Date: Tue, 3 Oct 2023 17:29:37 +0200 Subject: [PATCH] Make MKL pkg-config dependency work --- mesonbuild/dependencies/__init__.py | 1 + mesonbuild/dependencies/blas_lapack.py | 62 +++++++++++++++++-- .../frameworks/38 openblas/cblas_lapack.h | 27 +++++++- test cases/frameworks/38 openblas/meson.build | 26 +++++++- 4 files changed, 108 insertions(+), 8 deletions(-) diff --git a/mesonbuild/dependencies/__init__.py b/mesonbuild/dependencies/__init__.py index 755707c0e28e..97bd797c1e88 100644 --- a/mesonbuild/dependencies/__init__.py +++ b/mesonbuild/dependencies/__init__.py @@ -238,6 +238,7 @@ def __init__(self, name: str, environment: 'Environment', kwargs: T.Dict[str, T. # From blas_lapack: 'accelerate': 'blas_lapack', + 'mkl': 'blas_lapack', 'openblas': 'blas_lapack', # From platform: diff --git a/mesonbuild/dependencies/blas_lapack.py b/mesonbuild/dependencies/blas_lapack.py index 1e6aa30d1044..fb921db8258a 100644 --- a/mesonbuild/dependencies/blas_lapack.py +++ b/mesonbuild/dependencies/blas_lapack.py @@ -20,7 +20,7 @@ from .. import mlog from .. import mesonlib -from ..mesonlib import MachineChoice +from ..mesonlib import MachineChoice, OptionKey from .base import DependencyMethods, SystemDependency from .cmake import CMakeDependency @@ -462,11 +462,6 @@ def __init__(self, name: str, env: 'Environment', kwargs: T.Dict[str, T.Any], self.is_found = False -class OpenBLASMixin(): - def get_symbol_suffix(self) -> str: - return '' if self.interface == 'lp64' else '64_' - - class NetlibPkgConfigDependency(BLASLAPACKMixin, PkgConfigDependency): def __init__(self, name: str, env: 'Environment', kwargs: T.Dict[str, T.Any]) -> None: # TODO: add 'cblas' @@ -523,6 +518,53 @@ def get_symbol_suffix(self) -> str: return '$NEWLAPACK' if self.interface == 'lp64' else '$NEWLAPACK$ILP64' +class MKLPkgConfigDependency(BLASLAPACKMixin, PkgConfigDependency): + """ + pkg-config files for MKL were fixed recently, and should work from 2023.0 + onwards. Directly using a specific one like so should work: + + dependency('mkl-dynamic-ilp64-seq') + + The naming scheme is `mkl-libtype-interface-threading.pc`, with values: + - libtype: dynamic/static + - interface: lp64/ilp64 + - threading: seq/iomp/gomp/tbb + + Furthermore there is a pkg-config file for the Single Dynamic Library + (libmkl_rt.so) named `mkl-sdl.pc` (only added in 2023.0). + + Note that there is also an MKLPkgConfig dependency in scalapack.py, which + has more manual fixes. + """ + def __init__(self, name: str, env: 'Environment', kwargs: T.Dict[str, T.Any]) -> None: + self.feature_since = ('1.3.0', '') + self.parse_modules(kwargs) + + static_opt = kwargs.get('static', env.coredata.get_option(OptionKey('prefer_static'))) + libtype = 'static' if static_opt else 'dynamic' + + name = f'mkl-{libtype}-{self.interface}-seq' # FIXME: add threading module option + super().__init__(name, env, kwargs) + + def get_symbol_suffix(self) -> str: + return '' if self.interface == 'lp64' else '_64' + + +class MKLSystemDependency(BLASLAPACKMixin, SystemDependency): + def __init__(self, name: str, environment: 'Environment', kwargs: T.Dict[str, T.Any]) -> None: + super().__init__(name, environment, kwargs) + self.feature_since = ('1.3.0', '') + self.parse_modules(kwargs) + + # TODO: how to go about this? Use MKLROOT in addition to standard libdir(s)? + # support a machine file? + if self.is_found: + self.version = self.detect_mkl_version() + + def get_symbol_suffix(self) -> str: + return '' if self.interface == 'lp64' else '_64' + + packages['openblas'] = openblas_factory = DependencyFactory( 'openblas', [DependencyMethods.SYSTEM, DependencyMethods.PKGCONFIG, DependencyMethods.CMAKE], @@ -545,3 +587,11 @@ def get_symbol_suffix(self) -> str: [DependencyMethods.SYSTEM], system_class=AccelerateSystemDependency, ) + + +packages['mkl'] = mkl_factory = DependencyFactory( + 'mkl', + [DependencyMethods.PKGCONFIG], # DependencyMethods.SYSTEM + pkgconfig_class=MKLPkgConfigDependency, + #system_class=MKLSystemDependency, +) diff --git a/test cases/frameworks/38 openblas/cblas_lapack.h b/test cases/frameworks/38 openblas/cblas_lapack.h index 121e70d5b6e1..5b8ddc023d9d 100644 --- a/test cases/frameworks/38 openblas/cblas_lapack.h +++ b/test cases/frameworks/38 openblas/cblas_lapack.h @@ -8,8 +8,27 @@ // The end result after the standardization discussion in // https://github.com/Reference-LAPACK/lapack/issues/666 should be // `cblas_dgemm_64`, however that isn't yet final or implemented. +// +// # Actual symbols present in MKL: -// Name mangling adapted from NumPy's npy_cblas.h +// 00000000003e4970 T cblas_dgemm +// 00000000003e4970 T cblas_dgemm_ +// 00000000003e34e0 T cblas_dgemm_64 +// 00000000003e34e0 T cblas_dgemm_64_ +// +// 00000000004e9f80 T dgesv +// 00000000004e9f80 T dgesv_ +// 00000000004ea050 T dgesv_64 +// 00000000004ea050 T dgesv_64_ +// +// +// # Actual symbols present in OpenBLAS (in `libopenblas64`): +// +// 00000000000a3430 T cblas_dgemm64_ +// +// 00000000000a6e50 T dgesv_64_ + +// Name mangling adapted/extended from NumPy's npy_cblas.h #include #include #include @@ -44,9 +63,15 @@ BLAS_FUNC_CONCAT(name, suffix, suffix2) #define CBLAS_FUNC(name) BLAS_FUNC_EXPAND(name, , BLAS_SYMBOL_SUFFIX) +#ifdef OPENBLAS_ILP64_NAMING_SCHEME #define BLAS_FUNC(name) \ BLAS_FUNC_EXPAND(name, BLAS_FORTRAN_SUFFIX, BLAS_SYMBOL_SUFFIX) #define LAPACK_FUNC(name) BLAS_FUNC(name) +#else +#define BLAS_FUNC(name) \ + BLAS_FUNC_EXPAND(name, BLAS_SYMBOL_SUFFIX, BLAS_FORTRAN_SUFFIX) +#define LAPACK_FUNC(name) BLAS_FUNC(name) +#endif #ifdef HAVE_BLAS_ILP64 #define blas_int long diff --git a/test cases/frameworks/38 openblas/meson.build b/test cases/frameworks/38 openblas/meson.build index c7985e22ed25..9decb38c2507 100644 --- a/test cases/frameworks/38 openblas/meson.build +++ b/test cases/frameworks/38 openblas/meson.build @@ -36,7 +36,26 @@ accelerate64_dep = dependency('accelerate', required: false, ) -if not openblas_dep.found() and not openblas64_dep.found() and not accelerate_dep.found() +# MKL LP64 and ILP64 +mkl_dep = dependency('mkl', + modules: [ + 'interface: lp64', + 'cblas', + 'lapack', + ], + required: false, +) +mkl64_dep = dependency('mkl', + modules: [ + 'interface: ilp64', + 'cblas', + 'lapack', + ], + required: false, +) + + +if not openblas_dep.found() and not openblas64_dep.found() and not accelerate_dep.found() and not mkl_dep.found() error('MESON_SKIP_TEST: no BLAS/LAPACK libraries available') endif @@ -45,6 +64,8 @@ deps = { 'openblas64': openblas64_dep, 'accelerate': accelerate_dep, 'accelerate64': accelerate64_dep, + 'mkl': mkl_dep, + 'mkl64': mkl64_dep, } foreach name, dep : deps @@ -54,6 +75,9 @@ foreach name, dep : deps blas_c_args = ['-DBLAS_SYMBOL_SUFFIX=' + symbol_suffix] if blas_interface == 'ilp64' blas_c_args += ['-DHAVE_BLAS_ILP64'] + if 'openblas' in dep.name() + blas_c_args += ['-DOPENBLAS_ILP64_NAMING_SCHEME'] + endif elif blas_interface != 'lp64' error(f'no interface var for %name% dependency!') endif