diff --git a/CHANGELOG.md b/CHANGELOG.md index 14b021a..d267ff7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added * Added support for free-threaded (GIL-disabled) CPython builds: the Cython extension is compiled with `freethreading_compatible=True` and `_mklinit` declares `Py_MOD_GIL_NOT_USED`, so importing `mkl` no longer re-enables the GIL [gh-213](https://github.com/IntelPython/mkl-service/pull/213) +* Added support for new build option `ilp64` to initialize MKL with the ILP64 interface, which also resolves some build warnings [gh-184](https://github.com/IntelPython/mkl-service/pull/184) ### Changed * Raised the minimum build-time `Cython` requirement to `3.1.0`, the first release providing the `freethreading_compatible` directive [gh-213](https://github.com/IntelPython/mkl-service/pull/213) diff --git a/README.md b/README.md index 52620af..3eb6e97 100644 --- a/README.md +++ b/README.md @@ -54,3 +54,36 @@ then build against the existing installation with: ```sh python -m pip install --no-build-isolation --no-deps . ``` + +### Build options + +| Option | Type | Default | Description | +| ------- | ------- | ------- | ------------------------------------- | +| `ilp64` | boolean | `false` | Build with the oneMKL ILP64 interface | + +Options are passed using `-Csetup-args`: +```sh +python -m pip install . -Csetup-args=-Dilp64=true +``` + +By default `mkl-service` is built against the LP64 interface, in which oneMKL's +integer type `MKL_INT` is 32-bit. Enabling `ilp64` makes `MKL_INT` 64-bit +and requests the ILP64 interface layer from `libmkl_rt` on import. +Use it when the oneMKL libraries you link against provide the ILP64 interface. + +The Python API is identical in both configurations — no function signature or +return value changes. + +> **Warning:** the oneMKL interface layer is process-global and can only be +> selected before the first oneMKL call. `mkl-service` requests it on import, +> so an ILP64 build is order-dependent and unsafe to mix with LP64 +> consumers: +> +> * If imported before another oneMKL consumer initializes oneMKL, that +> consumer's LP64 calls get reinterpreted as ILP64. LAPACK routines in +> particular may crash. +> * If the other consumer initializes oneMKL first, the ILP64 request is ignored +> and the process stays LP64. +> +> Only enable `ilp64` when every consumer uses the ILP64 interface or +> `mkl-service` is the sole oneMKL consumer in the process. diff --git a/meson.build b/meson.build index 1b9ce89..0972a6b 100644 --- a/meson.build +++ b/meson.build @@ -15,6 +15,12 @@ project( py = import('python').find_installation(pure: false) c_args = ['-DNDEBUG'] +cmake_mkl_interface = 'lp64' + +if get_option('ilp64') + c_args += '-DMKL_ILP64' + cmake_mkl_interface = 'ilp64' +endif thread_dep = dependency('threads') @@ -24,6 +30,7 @@ mkl_dep = dependency('MKL', method: 'cmake', cmake_args: [ '-DMKL_ARCH=intel64', '-DMKL_LINK=sdl', + '-DMKL_INTERFACE=' + cmake_mkl_interface, ], required: true ) diff --git a/meson.options b/meson.options new file mode 100644 index 0000000..46117a3 --- /dev/null +++ b/meson.options @@ -0,0 +1,2 @@ +option('ilp64', type: 'boolean', value: false, + description: 'Build with MKL ILP64 interface') diff --git a/mkl/_mkl_service.pxd b/mkl/_mkl_service.pxd index 4cba157..ed5a106 100644 --- a/mkl/_mkl_service.pxd +++ b/mkl/_mkl_service.pxd @@ -24,12 +24,13 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -ctypedef long long MKL_INT64 -ctypedef unsigned long long MKL_UINT64 -ctypedef int MKL_INT - - cdef extern from "mkl.h": + # defer definition of integer types to mkl.h + # Cython will narrow the types based on what mkl.h defines + ctypedef long long MKL_INT64 + ctypedef unsigned long long MKL_UINT64 + ctypedef long long MKL_INT + # MKL Function Domains Constants int MKL_DOMAIN_BLAS int MKL_DOMAIN_FFT diff --git a/mkl/_mklinitmodule.c b/mkl/_mklinitmodule.c index 5a65b73..996ea59 100644 --- a/mkl/_mklinitmodule.c +++ b/mkl/_mklinitmodule.c @@ -25,8 +25,11 @@ static struct PyMethodDef methods[] = {{NULL, NULL, 0, NULL}}; #define MKL_SERVICE_INLINE inline #endif +#ifdef MKL_ILP64 static MKL_SERVICE_INLINE void _set_mkl_ilp64(void); +#else static MKL_SERVICE_INLINE void _set_mkl_lp64(void); +#endif static MKL_SERVICE_INLINE void _set_mkl_interface(void); static const char *mtlayer; @@ -151,6 +154,7 @@ static void _preload_threading_layer(void) return; } +#ifdef MKL_ILP64 static MKL_SERVICE_INLINE void _set_mkl_ilp64(void) { #ifdef USING_MKL_RT @@ -158,7 +162,7 @@ static MKL_SERVICE_INLINE void _set_mkl_ilp64(void) #endif return; } - +#else static MKL_SERVICE_INLINE void _set_mkl_lp64(void) { #ifdef USING_MKL_RT @@ -166,10 +170,15 @@ static MKL_SERVICE_INLINE void _set_mkl_lp64(void) #endif return; } +#endif static MKL_SERVICE_INLINE void _set_mkl_interface(void) { +#ifdef MKL_ILP64 + _set_mkl_ilp64(); +#else _set_mkl_lp64(); +#endif _preload_threading_layer(); }