Linking oneMKL in Python with Cython*
To link oneMKL in Python using Cython, you need to ensure that your setup can find and use oneMKL libraries. Here's a general approach:
- Install oneMKL: You can install oneMKL via conda* (conda install -c intel mkl) or download it directly from Intel.
- Configure Cython: In your setup.py, you can specify the oneMKL library paths and link them using scikit-build. Here's a simplified example using the official MKLConfig.cmake:
from skbuild import setup from setuptools import find_packages import os # Ensure MKLROOT is set mkl_root = os.environ.get('MKLROOT') if not mkl_root: raise EnvironmentError("MKLROOT environment variable is not set.") setup( name='your_package', version='0.1', packages=find_packages(), cmake_args=[ # Add the MKL module path to CMake's module path f'-DCMAKE_MODULE_PATH={mkl_root}/lib/cmake/mkl', ], install_requires=[ 'cython', 'numpy', ], ) - Cython Code: In your Cython code, you can use oneMKL functions by including the appropriate headers and linking against oneMKL libraries. Example:
# Import necessary Cython modules cimport cython from libc.stdlib cimport malloc, free # Import MKL headers cdef extern from "mkl.h": void cblas_dgemm(const int Order, const int TransA, const int TransB, const int M, const int N, const int K, const double alpha, const double *A, const int lda, const double *B, const int ldb, const double beta, double *C, const int ldc) @cython.boundscheck(False) # Disable bounds checking for performance @cython.wraparound(False) # Disable negative indexing for performance def matrix_multiply(double[:, :] A, double[:, :] B): cdef int m = A.shape[0] cdef int k = A.shape[1] cdef int n = B.shape[1] cdef double[:, :] C = cython.view.array(shape=(m, n), itemsize=sizeof(double), format="d") # Allocate memory for the result matrix cdef double* c_data = <double*>malloc(m * n * sizeof(double)) if not c_data: raise MemoryError("Unable to allocate memory for result matrix") try: # Perform matrix multiplication using MKL cblas_dgemm(101, 111, 111, m, n, k, 1.0, &A[0, 0], k, &B[0, 0], n, 0.0, c_data, n) # Copy result into Cython array for i in range(m): for j in range(n): C[i, j] = c_data[i * n + j] finally: # Free allocated memory free(c_data) return C
Using oneMKL in Python Libraries
To use oneMKL in Python libraries:
- Install oneMKL: Use conda to install oneMKL, which automatically configures SciPy to use oneMKL for BLAS/LAPACK operations.
- Environment Configuration: Ensure your environment variables are set correctly, such as LD_LIBRARY_PATH on Linux or PATH on Windows, to include oneMKL library paths.
oneMKL as an Optional Dependency in PyPI
To make oneMKL an optional dependency in a source distribution (sdist) on PyPI:
- Conditional Imports: Use try-except blocks to import oneMKL-related modules or functions, falling back to alternatives if oneMKL is not available.
- Extras: Define extras in your setup.py:
setup( name='your_package', version='0.1', install_requires=['numpy'], extras_require={ 'mkl': ['mkl'], }, )
oneMKL Variant in Conda Builds
For conda builds, especially on conda-forge:
- Meta.yaml: In your meta.yaml, specify oneMKL as a variant:
requirements: build: - {{ compiler('c') }} host: - python - numpy - mkl # Add oneMKL as a variant run: - python - numpy - mkl - Build Configuration: Use conda build tools to create different variants, ensuring oneMKL is included in the build matrix.