├── mkl
├── _version.py
├── _init_helper.py
├── __init__.py
├── _mkl_service.pxd
├── _mklinitmodule.c
├── tests
│ └── test_mkl_service.py
└── _mkl_service.pyx
├── .github
├── CODEOWNERS
├── dependabot.yml
└── workflows
│ ├── pre-commit.yml
│ ├── build-with-clang.yml
│ ├── openssf-scorecard.yml
│ └── conda-package.yml
├── .git-blame-ignore-revs
├── conda-recipe
├── conda_build_config.yaml
├── bld.bat
├── build.sh
└── meta.yaml
├── .flake8
├── .travis.yml
├── LICENSE.txt
├── README.md
├── .gitignore
├── examples
└── example.py
├── .pre-commit-config.yaml
├── pyproject.toml
├── CODE_OF_CONDUCT.md
├── setup.py
└── CHANGELOG.md
/mkl/_version.py:
--------------------------------------------------------------------------------
1 | __version__ = "2.7.0dev0"
2 |
--------------------------------------------------------------------------------
/.github/CODEOWNERS:
--------------------------------------------------------------------------------
1 | * @ndgrigorian @antonwolfy @xaleryb @jharlow-intel
2 |
--------------------------------------------------------------------------------
/.git-blame-ignore-revs:
--------------------------------------------------------------------------------
1 | # $ git config blame.ignoreRevsFile .git-blame-ignore-revs
2 |
3 | # Add pre-commit hooks
4 | 9c1fb5bd9b946c2eaaf1ea882e789efcccf66b53
5 |
--------------------------------------------------------------------------------
/.github/dependabot.yml:
--------------------------------------------------------------------------------
1 | version: 2
2 | updates:
3 | - package-ecosystem: "github-actions"
4 | directory: "/"
5 | schedule:
6 | interval: "weekly"
7 | day: "saturday"
8 | rebase-strategy: "disabled"
9 |
--------------------------------------------------------------------------------
/conda-recipe/conda_build_config.yaml:
--------------------------------------------------------------------------------
1 | c_compiler: # [linux]
2 | - gcc # [linux]
3 | cxx_compiler: # [linux]
4 | - gxx # [linux]
5 | cxx_compiler_version: # [linux]
6 | - '14' # [linux]
7 | c_stdlib: # [linux]
8 | - sysroot # [linux]
9 | c_stdlib_version: # [linux]
10 | - '2.28' # [linux]
11 | c_stdlib: # [win]
12 | - vs # [win]
13 | cxx_compiler: # [win]
14 | - vs2022 # [win]
15 | c_compiler: # [win]
16 | - vs2022 # [win]
17 |
--------------------------------------------------------------------------------
/conda-recipe/bld.bat:
--------------------------------------------------------------------------------
1 | echo on
2 | rem set CFLAGS=-I%PREFIX%\Library\include %CFLAGS%
3 | rem set LDFLAGS=/LIBPATH:%PREFIX% %LDFLAGS%
4 |
5 | set MKLROOT=%CONDA_PREFIX%
6 |
7 | "%PYTHON%" setup.py clean --all
8 |
9 | :: Make CMake verbose
10 | set "VERBOSE=1"
11 |
12 | :: -wnx flags mean: --wheel --no-isolation --skip-dependency-check
13 | %PYTHON% -m build -w -n -x
14 | if %ERRORLEVEL% neq 0 exit 1
15 |
16 | :: wheel file was renamed
17 | for /f %%f in ('dir /b /S .\dist') do (
18 | %PYTHON% -m pip install %%f ^
19 | --no-build-isolation ^
20 | --no-deps ^
21 | --only-binary :all: ^
22 | --no-index ^
23 | --prefix %PREFIX% ^
24 | -vv
25 | if %ERRORLEVEL% neq 0 exit 1
26 | )
27 |
28 | :: Copy wheel package
29 | if NOT "%WHEELS_OUTPUT_FOLDER%"=="" (
30 | copy dist\mkl_service*.whl %WHEELS_OUTPUT_FOLDER%
31 | if %ERRORLEVEL% neq 0 exit 1
32 | )
33 |
--------------------------------------------------------------------------------
/conda-recipe/build.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | set -ex
3 |
4 | export MKLROOT=$CONDA_PREFIX
5 |
6 | read -r GLIBC_MAJOR GLIBC_MINOR <<<"$(conda list '^sysroot_linux-64$' \
7 | | tail -n 1 | awk '{print $2}' | grep -oP '\d+' | head -n 2 | tr '\n' ' ')"
8 |
9 | ${PYTHON} setup.py clean --all
10 |
11 | # Make CMake verbose
12 | export VERBOSE=1
13 |
14 | # -wnx flags mean: --wheel --no-isolation --skip-dependency-check
15 | ${PYTHON} -m build -w -n -x
16 |
17 | ${PYTHON} -m wheel tags --remove \
18 | --platform-tag "manylinux_${GLIBC_MAJOR}_${GLIBC_MINOR}_x86_64" \
19 | dist/mkl_service*.whl
20 |
21 | ${PYTHON} -m pip install dist/mkl_service*.whl \
22 | --no-build-isolation \
23 | --no-deps \
24 | --only-binary :all: \
25 | --no-index \
26 | --prefix "${PREFIX}" \
27 | -vv
28 |
29 | # Copy wheel package
30 | if [[ -d "${WHEELS_OUTPUT_FOLDER}" ]]; then
31 | cp dist/mkl_service*.whl "${WHEELS_OUTPUT_FOLDER[@]}"
32 | fi
33 |
--------------------------------------------------------------------------------
/.github/workflows/pre-commit.yml:
--------------------------------------------------------------------------------
1 | name: pre-commit
2 |
3 | on:
4 | pull_request:
5 | push:
6 | branches: [master]
7 |
8 | permissions: read-all
9 |
10 | jobs:
11 | pre-commit:
12 | runs-on: ubuntu-latest
13 | timeout-minutes: 30
14 | steps:
15 | - name: Checkout repo
16 | uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
17 |
18 | - name: Set up python
19 | uses: actions/setup-python@83679a892e2d95755f2dac6acb0bfd1e9ac5d548 # v6.1.0
20 | with:
21 | python-version: '3.12'
22 |
23 | - name: Set up pip packages
24 | uses: BSFishy/pip-action@8f2d471d809dc20b6ada98c91910b6ae6243f318 # v1
25 | with:
26 | packages: |
27 | codespell
28 | pylint
29 |
30 | - name: Set up clang-format
31 | run: |
32 | sudo apt-get install -y clang-format-14
33 | sudo unlink /usr/bin/clang-format
34 | sudo ln -s /usr/bin/clang-format-14 /usr/bin/clang-format
35 | clang-format --version
36 |
37 | - name: Run pre-commit checks
38 | uses: pre-commit/action@2c7b3805fd2a0fd8c1884dcaebf91fc102a13ecd # v3.0.1
39 |
--------------------------------------------------------------------------------
/.flake8:
--------------------------------------------------------------------------------
1 | [flake8]
2 | extend-ignore =
3 | # whitespace before ':' (currently conflicts with black formatting):
4 | E203,
5 | # line too long (in docstrings):
6 | E501,
7 | # ‘from module import *’ used; unable to detect undefined names:
8 | F403,
9 | # doc line too long (105 > 80 characters):
10 | W505,
11 | # missing docstring in public module:
12 | D100,
13 | # missing docstring in public class:
14 | D101,
15 | # missing docstring in public method:
16 | D102,
17 | # missing docstring in public function:
18 | D103,
19 | # missing docstring in public package:
20 | D104,
21 | # missing docstring in magic method:
22 | D105,
23 | # missing docstring in __init__:
24 | D107,
25 | # no blank lines allowed after function docstring:
26 | D202,
27 | # 1 blank line required between summary line and description:
28 | D205,
29 | # first line should end with a period:
30 | D400,
31 | # first line should be in imperative mood:
32 | D401,
33 | # first line should not be the function's "signature":
34 | D402,
35 |
36 | per-file-ignores =
37 | mkl/__init__.py: E402, F401, F405
38 |
39 | filename = *.py, *.pyx, *.pxi, *.pxd
40 | max_line_length = 80
41 | max-doc-length = 80
42 | show-source = True
43 |
44 | # Print detailed statistic if any issue detected
45 | count = True
46 | statistics = True
47 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | matrix:
2 | include:
3 | - name: "Linux-Py2"
4 | os: linux
5 | dist: xenial
6 | env:
7 | - MINICONDA=Miniconda2-latest-Linux-x86_64.sh
8 | - PYVER="--python=27"
9 | - name: "Linux-Py3"
10 | os: linux
11 | dist: xenial
12 | env:
13 | - MINICONDA=Miniconda3-latest-Linux-x86_64.sh
14 | - PYVER=""
15 | - name: "OsX-Py2"
16 | os: osx
17 | osx_image: xcode8
18 | env:
19 | - MATRIX_EVAL="brew install gcc && CC=gcc-7 && CXX=g++-7"
20 | - MINICONDA=Miniconda3-latest-MacOSX-x86_64.sh
21 | - MACOSX_DEPLOYMENT_TARGET="10.9"
22 | - PYVER="--python=27"
23 | - name: "OsX-Py3"
24 | os: osx
25 | osx_image: xcode8
26 | env:
27 | - MATRIX_EVAL="brew install gcc && CC=gcc-7 && CXX=g++-7"
28 | - MINICONDA=Miniconda3-latest-MacOSX-x86_64.sh
29 | - MACOSX_DEPLOYMENT_TARGET="10.9"
30 | - PYVER=""
31 |
32 | install:
33 | - wget https://repo.continuum.io/miniconda/$MINICONDA -O miniconda.sh;
34 | - bash miniconda.sh -b -p $HOME/miniconda
35 | - export PATH="$HOME/miniconda/bin:$PATH"
36 | - hash -r
37 | - conda update --yes -q conda
38 | - conda install --yes conda-build
39 | # Useful for debugging any issues with conda
40 | - conda info -a
41 | - gcc -v
42 | - g++ -v
43 |
44 | script:
45 | - conda build -c conda-forge $PYVER --override-channels conda-recipe
46 |
--------------------------------------------------------------------------------
/LICENSE.txt:
--------------------------------------------------------------------------------
1 | Copyright (c) 2018, Intel Corporation
2 |
3 | Redistribution and use in source and binary forms, with or without
4 | modification, are permitted provided that the following conditions are met:
5 |
6 | * Redistributions of source code must retain the above copyright notice,
7 | this list of conditions and the following disclaimer.
8 | * Redistributions in binary form must reproduce the above copyright
9 | notice, this list of conditions and the following disclaimer in the
10 | documentation and/or other materials provided with the distribution.
11 | * Neither the name of Intel Corporation nor the names of its contributors
12 | may be used to endorse or promote products derived from this software
13 | without specific prior written permission.
14 |
15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
19 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
22 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
23 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # `mkl-service` - Python package for run-time control of Intel® oneAPI Math Kernel Library (oneMKL).
2 | [](https://github.com/IntelPython/mkl-service/actions/workflows/conda-package.yml)
3 | [](https://github.com/IntelPython/mkl-service/actions/workflows/build-with-clang.yml)
4 | [](https://securityscorecards.dev/viewer/?uri=github.com/IntelPython/mkl-service)
5 |
6 |
7 | ---
8 |
9 | To install conda package, use `conda install -c https://software.repos.intel.com/python/conda/ mkl-service`, or `conda install -c conda-forge mkl-service`.
10 |
11 | To install PyPI package, use `python -m pip install mkl-service`.
12 |
13 | ---
14 |
15 | Intel® oneAPI Math Kernel Library (oneMKL) supports functions are subdivided into the following groups according to their purpose:
16 | - Version Information
17 | - Threading Control
18 | - Timing
19 | - Memory Management
20 | - Conditional Numerical Reproducibility Control
21 | - Miscellaneous
22 |
23 | A short example, illustrating its use:
24 |
25 | ```python
26 | >>> import mkl
27 | >>> mkl.domain_set_num_threads(1, domain="fft") # oneMKL FFT functions to run sequentially
28 | # 'success'
29 | ```
30 |
31 | For more information about the usage of support functions see [Developer Reference for Intel® oneAPI Math Kernel Library for C](https://www.intel.com/content/www/us/en/docs/onemkl/developer-reference-c/2025-2/support-functions.html).
32 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Cython
2 | mkl/_mkl_service.c
3 |
4 | # Byte-compiled / optimized / DLL files
5 | __pycache__/
6 | *.py[cod]
7 | *$py.class
8 |
9 | # C extensions
10 | *.so
11 |
12 | # Distribution / packaging
13 | .Python
14 | env/
15 | build/
16 | develop-eggs/
17 | dist/
18 | downloads/
19 | eggs/
20 | .eggs/
21 | lib/
22 | lib64/
23 | parts/
24 | sdist/
25 | var/
26 | wheels/
27 | *.egg-info/
28 | .installed.cfg
29 | *.egg
30 |
31 | # PyInstaller
32 | # Usually these files are written by a python script from a template
33 | # before PyInstaller builds the exe, so as to inject date/other infos into it.
34 | *.manifest
35 | *.spec
36 |
37 | # Installer logs
38 | pip-log.txt
39 | pip-delete-this-directory.txt
40 |
41 | # Unit test / coverage reports
42 | htmlcov/
43 | .tox/
44 | .coverage
45 | .coverage.*
46 | .cache
47 | nosetests.xml
48 | coverage.xml
49 | *.cover
50 | .hypothesis/
51 |
52 | # Translations
53 | *.mo
54 | *.pot
55 |
56 | # Django stuff:
57 | *.log
58 | local_settings.py
59 |
60 | # Flask stuff:
61 | instance/
62 | .webassets-cache
63 |
64 | # Scrapy stuff:
65 | .scrapy
66 |
67 | # Sphinx documentation
68 | docs/_build/
69 |
70 | # PyBuilder
71 | target/
72 |
73 | # Jupyter Notebook
74 | .ipynb_checkpoints
75 |
76 | # pyenv
77 | .python-version
78 |
79 | # celery beat schedule file
80 | celerybeat-schedule
81 |
82 | # SageMath parsed files
83 | *.sage.py
84 |
85 | # dotenv
86 | .env
87 |
88 | # virtualenv
89 | .venv
90 | venv/
91 | ENV/
92 |
93 | # Spyder project settings
94 | .spyderproject
95 | .spyproject
96 |
97 | # Rope project settings
98 | .ropeproject
99 |
100 | # mkdocs documentation
101 | /site
102 |
103 | # mypy
104 | .mypy_cache/
105 |
--------------------------------------------------------------------------------
/conda-recipe/meta.yaml:
--------------------------------------------------------------------------------
1 | package:
2 | name: mkl-service
3 | version: {{ GIT_DESCRIBE_TAG }}
4 |
5 | source:
6 | path: ..
7 |
8 | build:
9 | number: {{ GIT_DESCRIBE_NUMBER }}
10 | script_env:
11 | - WHEELS_OUTPUT_FOLDER
12 | ignore_run_exports:
13 | - blas
14 | - mkl-service
15 |
16 | requirements:
17 | build:
18 | - {{ compiler('c') }}
19 | - {{ stdlib('c') }}
20 | host:
21 | - python
22 | - python-gil # [py>=314]
23 | - pip >=25.0
24 | - setuptools >=77
25 | - mkl-devel
26 | - cython
27 | - wheel >=0.45.1
28 | - python-build >=1.2.2
29 | run:
30 | - python
31 | - python-gil # [py>=314]
32 | - {{ pin_compatible('mkl') }}
33 |
34 | test:
35 | requires:
36 | - pytest
37 | imports:
38 | - mkl
39 | commands:
40 | - pytest -vv --pyargs mkl
41 |
42 | about:
43 | home: http://github.com/IntelPython/mkl-service
44 | license: BSD-3-Clause
45 | license_file: LICENSE.txt
46 | summary: Python hooks for Intel® oneAPI Math Kernel Library (oneMKL) runtime control settings
47 | description: |
48 | LEGAL NOTICE: Use of this software package is subject to the
49 | software license agreement (as set forth above, in the license section of
50 | the installed Conda package and/or the README file) and all notices,
51 | disclaimers or license terms for third party or open source software
52 | included in or with the software.
53 |
54 | EULA: BSD-3-Clause
55 |
56 |
57 | extra:
58 | recipe-maintainers:
59 | - ekomarova
60 | - vtavana
61 | - xaleryb
62 |
--------------------------------------------------------------------------------
/mkl/_init_helper.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2025, Intel Corporation
2 | #
3 | # Redistribution and use in source and binary forms, with or without
4 | # modification, are permitted provided that the following conditions are met:
5 | #
6 | # * Redistributions of source code must retain the above copyright notice,
7 | # this list of conditions and the following disclaimer.
8 | # * Redistributions in binary form must reproduce the above copyright
9 | # notice, this list of conditions and the following disclaimer in the
10 | # documentation and/or other materials provided with the distribution.
11 | # * Neither the name of Intel Corporation nor the names of its contributors
12 | # may be used to endorse or promote products derived from this software
13 | # without specific prior written permission.
14 | #
15 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16 | # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 | # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 | # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
19 | # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 | # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21 | # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
22 | # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
23 | # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24 | # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 |
26 | import os
27 | import os.path
28 | import sys
29 |
30 | is_venv_win32 = (
31 | sys.platform == "win32"
32 | and sys.base_exec_prefix != sys.exec_prefix
33 | and os.path.isfile(os.path.join(sys.exec_prefix, "pyvenv.cfg"))
34 | )
35 |
36 | if is_venv_win32:
37 | # In Windows venv: add Library/bin to PATH for proper DLL loading
38 | dll_dir = os.path.join(sys.exec_prefix, "Library", "bin")
39 | if os.path.isdir(dll_dir):
40 | os.add_dll_directory(dll_dir)
41 |
42 | del is_venv_win32
43 |
--------------------------------------------------------------------------------
/.github/workflows/build-with-clang.yml:
--------------------------------------------------------------------------------
1 | name: Build project with IntelLLVM clang compiler
2 |
3 | on:
4 | push:
5 | branches:
6 | - master
7 | pull_request:
8 |
9 | permissions: read-all
10 |
11 | jobs:
12 | build-with-clang:
13 | runs-on: ubuntu-latest
14 |
15 | strategy:
16 | matrix:
17 | python: ["3.10", "3.11", "3.12", "3.13"]
18 |
19 | env:
20 | ONEAPI_ROOT: /opt/intel/oneapi
21 |
22 | defaults:
23 | run:
24 | shell: bash -el {0}
25 |
26 | steps:
27 | - name: Cancel Previous Runs
28 | uses: styfle/cancel-workflow-action@85880fa0301c86cca9da44039ee3bb12d3bedbfa # 0.12.1
29 | with:
30 | access_token: ${{ github.token }}
31 |
32 | - name: Add Intel repository
33 | run: |
34 | wget https://apt.repos.intel.com/intel-gpg-keys/GPG-PUB-KEY-INTEL-SW-PRODUCTS-2023.PUB
35 | sudo apt-key add GPG-PUB-KEY-INTEL-SW-PRODUCTS-2023.PUB
36 | rm GPG-PUB-KEY-INTEL-SW-PRODUCTS-2023.PUB
37 | sudo add-apt-repository "deb https://apt.repos.intel.com/oneapi all main"
38 | sudo apt-get update
39 |
40 | - name: Install Intel OneAPI
41 | run: |
42 | sudo apt-get install intel-oneapi-compiler-dpcpp-cpp
43 | sudo apt-get install intel-oneapi-tbb
44 | sudo apt-get install intel-oneapi-mkl-devel
45 |
46 | - name: Setup Python
47 | uses: actions/setup-python@83679a892e2d95755f2dac6acb0bfd1e9ac5d548 # v6.1.0
48 | with:
49 | python-version: ${{ matrix.python }}
50 | architecture: x64
51 |
52 | - name: Checkout repo
53 | uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
54 | with:
55 | fetch-depth: 0
56 |
57 | - name: Install mkl-service dependencies
58 | uses: BSFishy/pip-action@8f2d471d809dc20b6ada98c91910b6ae6243f318 # v1
59 | with:
60 | packages: |
61 | cython
62 | setuptools>=77
63 | pytest
64 |
65 | - name: List oneAPI folder content
66 | run: ls ${{ env.ONEAPI_ROOT }}/compiler
67 |
68 | - name: Build mkl-service
69 | run: |
70 | source ${{ env.ONEAPI_ROOT }}/setvars.sh
71 | echo $CMPLR_ROOT
72 | export CC=$CMPLR_ROOT/bin/icx
73 | export CFLAGS="${CFLAGS} -fno-fast-math"
74 | python setup.py develop
75 |
76 | - name: Run mkl-service tests
77 | run: |
78 | source ${{ env.ONEAPI_ROOT }}/setvars.sh
79 | pytest -s -v --pyargs mkl
80 |
--------------------------------------------------------------------------------
/mkl/__init__.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2018, Intel Corporation
2 | #
3 | # Redistribution and use in source and binary forms, with or without
4 | # modification, are permitted provided that the following conditions are met:
5 | #
6 | # * Redistributions of source code must retain the above copyright notice,
7 | # this list of conditions and the following disclaimer.
8 | # * Redistributions in binary form must reproduce the above copyright
9 | # notice, this list of conditions and the following disclaimer in the
10 | # documentation and/or other materials provided with the distribution.
11 | # * Neither the name of Intel Corporation nor the names of its contributors
12 | # may be used to endorse or promote products derived from this software
13 | # without specific prior written permission.
14 | #
15 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16 | # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 | # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 | # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
19 | # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 | # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21 | # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
22 | # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
23 | # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24 | # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 |
26 | import sys
27 |
28 | from . import _init_helper
29 |
30 |
31 | class RTLD_for_MKL:
32 | def __init__(self):
33 | self.saved_rtld = None
34 |
35 | def __enter__(self):
36 | import ctypes
37 |
38 | try:
39 | self.saved_rtld = sys.getdlopenflags()
40 | # python loads libraries with RTLD_LOCAL, but MKL requires
41 | # RTLD_GLOBAL pre-load MKL with RTLD_GLOBAL before loading
42 | # the native extension
43 | sys.setdlopenflags(self.saved_rtld | ctypes.RTLD_GLOBAL)
44 | except AttributeError:
45 | pass
46 | del ctypes
47 |
48 | def __exit__(self, *args):
49 | if self.saved_rtld:
50 | sys.setdlopenflags(self.saved_rtld)
51 | self.saved_rtld = None
52 |
53 |
54 | with RTLD_for_MKL():
55 | from . import _mklinit
56 |
57 | del RTLD_for_MKL
58 | del sys
59 |
60 | from ._py_mkl_service import *
61 | from ._version import __version__
62 |
63 | del _init_helper
64 |
--------------------------------------------------------------------------------
/examples/example.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2018, Intel Corporation
2 | #
3 | # Redistribution and use in source and binary forms, with or without
4 | # modification, are permitted provided that the following conditions are met:
5 | #
6 | # * Redistributions of source code must retain the above copyright notice,
7 | # this list of conditions and the following disclaimer.
8 | # * Redistributions in binary form must reproduce the above copyright
9 | # notice, this list of conditions and the following disclaimer in the
10 | # documentation and/or other materials provided with the distribution.
11 | # * Neither the name of Intel Corporation nor the names of its contributors
12 | # may be used to endorse or promote products derived from this software
13 | # without specific prior written permission.
14 | #
15 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16 | # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 | # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 | # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
19 | # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 | # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21 | # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
22 | # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
23 | # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24 | # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 |
26 | # pylint: disable=no-member
27 |
28 | import re
29 |
30 | import mkl
31 |
32 |
33 | def enable_best_instructions_set():
34 | for instructions_set in ["avx512", "avx2", "avx", "sse4_2"]:
35 | if mkl.enable_instructions(instructions_set) == "success":
36 | result = instructions_set
37 | break
38 | else:
39 | result = "error"
40 |
41 | return result
42 |
43 |
44 | def is_max_supported_instructions_set(instructions_set):
45 | result = False
46 | if re.search(
47 | instructions_set.replace("4_2", "4.2"),
48 | mkl.get_version()["Processor"].decode(),
49 | re.IGNORECASE,
50 | ):
51 | result = True
52 |
53 | return result
54 |
55 |
56 | if __name__ == "__main__":
57 | time_begin = mkl.dsecnd()
58 | print(mkl.get_version_string())
59 |
60 | instructions_set = enable_best_instructions_set()
61 | print("Enable snstructions set: " + str(instructions_set))
62 |
63 | is_max = is_max_supported_instructions_set(instructions_set)
64 | print("Is the best supported instructions set: " + str(is_max))
65 |
66 | time_end = mkl.dsecnd()
67 | print("Execution time: " + str(time_end - time_begin))
68 |
--------------------------------------------------------------------------------
/.pre-commit-config.yaml:
--------------------------------------------------------------------------------
1 | repos:
2 | - repo: https://github.com/pre-commit/pre-commit-hooks
3 | rev: v6.0.0
4 | hooks:
5 | - id: check-ast
6 | - id: check-builtin-literals
7 | - id: check-case-conflict
8 | - id: check-executables-have-shebangs
9 | - id: check-merge-conflict
10 | - id: check-toml
11 | - id: debug-statements
12 | - id: destroyed-symlinks
13 | - id: end-of-file-fixer
14 | - id: fix-byte-order-marker
15 | - id: mixed-line-ending
16 | - id: trailing-whitespace
17 |
18 | - repo: https://github.com/pre-commit/pygrep-hooks
19 | rev: v1.10.0
20 | hooks:
21 | - id: python-check-blanket-noqa
22 | - id: python-check-blanket-type-ignore
23 | - id: python-check-mock-methods
24 | - id: python-no-eval
25 | - id: python-no-log-warn
26 | - id: python-use-type-annotations
27 | - id: rst-backticks
28 | - id: rst-directive-colons
29 | - id: rst-inline-touching-normal
30 | - id: text-unicode-replacement-char
31 |
32 | - repo: https://github.com/codespell-project/codespell
33 | rev: v2.4.1
34 | hooks:
35 | - id: codespell
36 | additional_dependencies:
37 | - tomli
38 |
39 | - repo: https://github.com/psf/black
40 | rev: 25.9.0
41 | hooks:
42 | - id: black
43 | exclude: "_vendored/conv_template.py"
44 |
45 | - repo: https://github.com/pocc/pre-commit-hooks
46 | rev: v1.3.5
47 | hooks:
48 | - id: clang-format
49 | args: ["-i"]
50 |
51 | - repo: https://github.com/MarcoGorelli/cython-lint
52 | rev: v0.17.0
53 | hooks:
54 | - id: cython-lint
55 | - id: double-quote-cython-strings
56 |
57 | - repo: https://github.com/pycqa/flake8
58 | rev: 7.3.0
59 | hooks:
60 | - id: flake8
61 | args: ["--config=.flake8"]
62 | additional_dependencies:
63 | - flake8-docstrings==1.7.0
64 | - flake8-bugbear==24.4.26
65 |
66 | - repo: https://github.com/pycqa/isort
67 | rev: 6.1.0
68 | hooks:
69 | - id: isort
70 | name: isort (python)
71 | - id: isort
72 | name: isort (cython)
73 | types: [cython]
74 | - id: isort
75 | name: isort (pyi)
76 | types: [pyi]
77 |
78 | - repo: https://github.com/macisamuele/language-formatters-pre-commit-hooks
79 | rev: v2.15.0
80 | hooks:
81 | - id: pretty-format-toml
82 | args: [--autofix]
83 |
84 | - repo: local
85 | hooks:
86 | - id: pylint
87 | name: pylint
88 | entry: pylint
89 | language: system
90 | types: [python]
91 | require_serial: true
92 | args:
93 | [
94 | "-rn", # Only display messages
95 | "-sn", # Don't display the score
96 | "--errors-only",
97 | "--disable=import-error",
98 | ]
99 |
100 | - repo: https://github.com/jumanjihouse/pre-commit-hooks
101 | rev: 3.0.0
102 | hooks:
103 | - id: shellcheck
104 |
--------------------------------------------------------------------------------
/.github/workflows/openssf-scorecard.yml:
--------------------------------------------------------------------------------
1 | # This workflow uses actions that are not certified by GitHub. They are provided
2 | # by a third-party and are governed by separate terms of service, privacy
3 | # policy, and support documentation.
4 |
5 | name: Scorecard supply-chain security
6 | on:
7 | # For Branch-Protection check. Only the default branch is supported. See
8 | # https://github.com/ossf/scorecard/blob/main/docs/checks.md#branch-protection
9 | branch_protection_rule:
10 | # To guarantee Maintained check is occasionally updated. See
11 | # https://github.com/ossf/scorecard/blob/main/docs/checks.md#maintained
12 | schedule:
13 | - cron: '28 2 * * 1'
14 | - cron: '28 2 * * 4'
15 | push:
16 | branches: [ "master" ]
17 |
18 | # Declare default permissions as read only.
19 | permissions: read-all
20 |
21 | jobs:
22 | analysis:
23 | name: Scorecard analysis
24 | runs-on: ubuntu-latest
25 | timeout-minutes: 30
26 | permissions:
27 | # Needed to upload the results to code-scanning dashboard.
28 | security-events: write
29 | # Needed to publish results and get a badge (see publish_results below).
30 | id-token: write
31 | # Uncomment the permissions below if installing in a private repository.
32 | # contents: read
33 | # actions: read
34 |
35 | steps:
36 | - name: "Checkout code"
37 | uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
38 | with:
39 | persist-credentials: false
40 |
41 | - name: "Run analysis"
42 | uses: ossf/scorecard-action@4eaacf0543bb3f2c246792bd56e8cdeffafb205a # v2.4.3
43 | with:
44 | results_file: results.sarif
45 | results_format: sarif
46 | # (Optional) "write" PAT token. Uncomment the `repo_token` line below if:
47 | # - you want to enable the Branch-Protection check on a *public* repository, or
48 | # - you are installing Scorecard on a *private* repository
49 | # To create the PAT, follow the steps in https://github.com/ossf/scorecard-action#authentication-with-pat.
50 | # repo_token: ${{ secrets.SCORECARD_TOKEN }}
51 |
52 | # Public repositories:
53 | # - Publish results to OpenSSF REST API for easy access by consumers
54 | # - Allows the repository to include the Scorecard badge.
55 | # - See https://github.com/ossf/scorecard-action#publishing-results.
56 | # For private repositories:
57 | # - `publish_results` will always be set to `false`, regardless
58 | # of the value entered here.
59 | publish_results: true
60 |
61 | # Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF
62 | # format to the repository Actions tab.
63 | - name: "Upload artifact"
64 | uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
65 | with:
66 | name: SARIF file
67 | path: results.sarif
68 | retention-days: 14
69 |
70 | # Upload the results to GitHub's code scanning dashboard.
71 | - name: "Upload to code-scanning"
72 | uses: github/codeql-action/upload-sarif@fdbfb4d2750291e159f0156def62b853c2798ca2 # v4.31.5
73 | with:
74 | sarif_file: results.sarif
75 |
--------------------------------------------------------------------------------
/pyproject.toml:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2025, Intel Corporation
2 | #
3 | # Redistribution and use in source and binary forms, with or without
4 | # modification, are permitted provided that the following conditions are met:
5 | #
6 | # * Redistributions of source code must retain the above copyright notice,
7 | # this list of conditions and the following disclaimer.
8 | # * Redistributions in binary form must reproduce the above copyright
9 | # notice, this list of conditions and the following disclaimer in the
10 | # documentation and/or other materials provided with the distribution.
11 | # * Neither the name of Intel Corporation nor the names of its contributors
12 | # may be used to endorse or promote products derived from this software
13 | # without specific prior written permission.
14 | #
15 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16 | # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 | # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 | # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
19 | # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 | # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21 | # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
22 | # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
23 | # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24 | # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 |
26 | [build-system]
27 | build-backend = "setuptools.build_meta"
28 | requires = ["setuptools>=77", "Cython", "wheel>=0.45.1", "build>=1.2.2"]
29 |
30 | [project]
31 | authors = [
32 | {name = "Intel Corporation", email = "scripting@intel.com"}
33 | ]
34 | classifiers = [
35 | "Development Status :: 5 - Production/Stable",
36 | "Intended Audience :: Science/Research",
37 | "Intended Audience :: Developers",
38 | "Programming Language :: C",
39 | "Programming Language :: Python",
40 | "Programming Language :: Python :: 3",
41 | "Programming Language :: Python :: 3.10",
42 | "Programming Language :: Python :: 3.11",
43 | "Programming Language :: Python :: 3.12",
44 | "Programming Language :: Python :: 3.13",
45 | "Programming Language :: Python :: 3.14",
46 | "Programming Language :: Python :: Implementation :: CPython",
47 | "Topic :: Software Development",
48 | "Topic :: Utilities",
49 | "Operating System :: Microsoft :: Windows",
50 | "Operating System :: POSIX",
51 | "Operating System :: Unix"
52 | ]
53 | dependencies = []
54 | description = "Python hooks for Intel® oneAPI Math Kernel Library (oneMKL) runtime control settings"
55 | dynamic = ["version"]
56 | keywords = ["MKL"]
57 | license = "BSD-3-Clause"
58 | name = "mkl-service"
59 | readme = {file = "README.md", content-type = "text/markdown"}
60 | requires-python = ">=3.10,<3.15"
61 |
62 | [project.optional-dependencies]
63 | test = ["pytest"]
64 |
65 | [project.urls]
66 | Download = "http://github.com/IntelPython/mkl-service"
67 | Homepage = "http://github.com/IntelPython/mkl-service"
68 |
69 | [tool.setuptools]
70 | include-package-data = true
71 | packages = ["mkl"]
72 |
73 | [tool.setuptools.dynamic]
74 | version = {attr = "mkl._version.__version__"}
75 |
76 | [tool.setuptools.package-data]
77 | "mkl" = ["tests/*.py"]
78 |
--------------------------------------------------------------------------------
/CODE_OF_CONDUCT.md:
--------------------------------------------------------------------------------
1 | # Contributor Covenant Code of Conduct
2 |
3 | ## Our Pledge
4 |
5 | In the interest of fostering an open and welcoming environment, we as
6 | contributors and maintainers pledge to making participation in our project and
7 | our community a harassment-free experience for everyone, regardless of age, body
8 | size, disability, ethnicity, sex characteristics, gender identity and expression,
9 | level of experience, education, socio-economic status, nationality, personal
10 | appearance, race, religion, or sexual identity and orientation.
11 |
12 | ## Our Standards
13 |
14 | Examples of behavior that contributes to creating a positive environment
15 | include:
16 |
17 | * Using welcoming and inclusive language
18 | * Being respectful of differing viewpoints and experiences
19 | * Gracefully accepting constructive criticism
20 | * Focusing on what is best for the community
21 | * Showing empathy towards other community members
22 |
23 | Examples of unacceptable behavior by participants include:
24 |
25 | * The use of sexualized language or imagery and unwelcome sexual attention or
26 | advances
27 | * Trolling, insulting/derogatory comments, and personal or political attacks
28 | * Public or private harassment
29 | * Publishing others' private information, such as a physical or electronic
30 | address, without explicit permission
31 | * Other conduct which could reasonably be considered inappropriate in a
32 | professional setting
33 |
34 | ## Our Responsibilities
35 |
36 | Project maintainers are responsible for clarifying the standards of acceptable
37 | behavior and are expected to take appropriate and fair corrective action in
38 | response to any instances of unacceptable behavior.
39 |
40 | Project maintainers have the right and responsibility to remove, edit, or
41 | reject comments, commits, code, wiki edits, issues, and other contributions
42 | that are not aligned to this Code of Conduct, or to ban temporarily or
43 | permanently any contributor for other behaviors that they deem inappropriate,
44 | threatening, offensive, or harmful.
45 |
46 | ## Scope
47 |
48 | This Code of Conduct applies both within project spaces and in public spaces
49 | when an individual is representing the project or its community. Examples of
50 | representing a project or community include using an official project e-mail
51 | address, posting via an official social media account, or acting as an appointed
52 | representative at an online or offline event. Representation of a project may be
53 | further defined and clarified by project maintainers.
54 |
55 | ## Enforcement
56 |
57 | Instances of abusive, harassing, or otherwise unacceptable behavior may be
58 | reported by contacting the project team at scripting@intel.com. All
59 | complaints will be reviewed and investigated and will result in a response that
60 | is deemed necessary and appropriate to the circumstances. The project team is
61 | obligated to maintain confidentiality with regard to the reporter of an incident.
62 | Further details of specific enforcement policies may be posted separately.
63 |
64 | Project maintainers who do not follow or enforce the Code of Conduct in good
65 | faith may face temporary or permanent repercussions as determined by other
66 | members of the project's leadership.
67 |
68 | ## Attribution
69 |
70 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
71 | available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
72 |
73 | [homepage]: https://www.contributor-covenant.org
74 |
75 | For answers to common questions about this code of conduct, see
76 | https://www.contributor-covenant.org/faq
77 |
--------------------------------------------------------------------------------
/setup.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2018, Intel Corporation
2 | #
3 | # Redistribution and use in source and binary forms, with or without
4 | # modification, are permitted provided that the following conditions are met:
5 | #
6 | # * Redistributions of source code must retain the above copyright notice,
7 | # this list of conditions and the following disclaimer.
8 | # * Redistributions in binary form must reproduce the above copyright
9 | # notice, this list of conditions and the following disclaimer in the
10 | # documentation and/or other materials provided with the distribution.
11 | # * Neither the name of Intel Corporation nor the names of its contributors
12 | # may be used to endorse or promote products derived from this software
13 | # without specific prior written permission.
14 | #
15 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16 | # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 | # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 | # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
19 | # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 | # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21 | # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
22 | # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
23 | # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24 | # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 |
26 |
27 | import os
28 | import sys
29 | from os.path import join
30 |
31 | import Cython.Build
32 | from setuptools import Extension, setup
33 |
34 |
35 | def extensions():
36 | mkl_root = os.environ.get("MKLROOT", None)
37 | if mkl_root:
38 | mkl_info = {
39 | "include_dirs": [join(mkl_root, "include")],
40 | "library_dirs": [join(mkl_root, "lib"), join(mkl_root, "lib", "intel64")],
41 | "libraries": ["mkl_rt"],
42 | }
43 | else:
44 | raise ValueError("MKLROOT environment variable not set.")
45 |
46 | if sys.platform != "win32":
47 | mkl_info["rpaths"] = ["$ORIGIN/../..", "$ORIGIN/../../.."]
48 |
49 | mkl_include_dirs = mkl_info.get("include_dirs", [])
50 | mkl_library_dirs = mkl_info.get("library_dirs", [])
51 | mkl_libraries = mkl_info.get("libraries", ["mkl_rt"])
52 | mkl_rpaths = mkl_info.get("rpaths", [])
53 |
54 | defs = []
55 | if any(["mkl_rt" in li for li in mkl_libraries]):
56 | # libs += ["dl"] - by default on Linux
57 | defs += [("USING_MKL_RT", None)]
58 |
59 | extensions = []
60 | extensions.append(
61 | Extension(
62 | "mkl._mklinit",
63 | sources=[join("mkl", "_mklinitmodule.c")],
64 | include_dirs=mkl_include_dirs,
65 | libraries=mkl_libraries + (["pthread"] if os.name == "posix" else []),
66 | library_dirs=mkl_library_dirs,
67 | runtime_library_dirs=mkl_rpaths,
68 | extra_compile_args=[
69 | "-DNDEBUG"
70 | # "-g", "-O2", "-Wall",
71 | ],
72 | define_macros=defs,
73 | )
74 | )
75 |
76 | extensions.append(
77 | Extension(
78 | "mkl._py_mkl_service",
79 | sources=[join("mkl", "_mkl_service.pyx")],
80 | include_dirs=mkl_include_dirs,
81 | library_dirs=mkl_library_dirs,
82 | libraries=mkl_libraries,
83 | runtime_library_dirs=mkl_rpaths,
84 | extra_compile_args=[
85 | "-DNDEBUG"
86 | # "-g", "-O2", "-Wall",
87 | ],
88 | )
89 | )
90 |
91 | return extensions
92 |
93 |
94 | setup(
95 | cmdclass={"build_ext": Cython.Build.build_ext},
96 | ext_modules=extensions(),
97 | zip_safe=False,
98 | )
99 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # changelog
2 | All notable changes to this project will be documented in this file.
3 |
4 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
5 | and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6 |
7 | ## [dev] (MM/DD/YYYY)
8 |
9 | ### Removed
10 | * Dropped support for Python 3.9 [gh-118](https://github.com/IntelPython/mkl-service/pull/118)
11 |
12 | ## [2.6.1] (11/25/2025)
13 |
14 | ### Fixed
15 | * Fixed the run-time dependencies of `mkl-service` package to explicitly depend on a non–free-threaded (GIL-enabled) Python [gh-111](github.com/IntelPython/mkl-service/pull/111)
16 |
17 | ## [2.6.0] (10/06/2025)
18 |
19 | ### Added
20 | * Enabled support of Python 3.14 [gh-100](https://github.com/IntelPython/mkl-service/pull/100)
21 |
22 | ### Changed
23 | * Used `GIT_DESCRIBE_TAG` and `GIT_DESCRIBE_NUMBER` in `meta.yaml` instead of manual stepping the numbers [gh-98](github.com/IntelPython/mkl-service/pull/98)
24 |
25 | ## [2.5.2] (07/01/2025)
26 |
27 | ### Fixed
28 | * Updated `meta.yaml` with proper license description to pass the validation rules [gh-87](github.com/IntelPython/mkl-service/pull/87)
29 |
30 | ## [2.5.1] (06/27/2025)
31 |
32 | ### Fixed
33 | * Resolved import issue in the virtual environment which broke loading of MKL libs [gh-85](github.com/IntelPython/mkl-service/pull/85)
34 |
35 | ## [2.5.0] (06/03/2025)
36 |
37 | ### Added
38 | * Added support for python 3.13 [gh-72](github.com/IntelPython/mkl-service/pull/72)
39 | * Added support in virtual environment out of the box [gh-79](github.com/IntelPython/mkl-service/pull/79)
40 |
41 | ### Changed
42 | * Migrated from `setup.py` to `pyproject.toml` [gh-66](github.com/IntelPython/mkl-service/pull/66)
43 |
44 | ## [2.4.2] (10/12/2024)
45 |
46 | Tests checking library version moved to the end of the test suite, as after it is run, the state of the library is finalized, and tests that modify that state may fail.
47 |
48 | Updated installation instructions.
49 |
50 | ## [2.4.1]
51 |
52 | Transition from `nose` to `unittest` and then to `pytest` to enable support for Python 3.12.
53 |
54 | Added Github Actions CI.
55 |
56 | Removed `six` as a dependency.
57 |
58 | ## [2.4.0.post1]
59 |
60 | Update description for PyPI package installation
61 |
62 | ## [2.4.0]
63 |
64 | Fixed issue [#14](https://github.com/IntelPython/mkl-service/issues/14).
65 |
66 | Added [`mkl.set_num_stripes`](https://software.intel.com/content/www/us/en/develop/documentation/onemkl-developer-reference-c/top/support-functions/threading-control/mkl-set-num-stripes.html) and [`mkl.get_num_stripes`](https://software.intel.com/content/www/us/en/develop/documentation/onemkl-developer-reference-c/top/support-functions/threading-control/mkl-get-num-stripes.html)
67 |
68 | Also expanded support `isa` keyword argument values in `mkl.enable_instructions(isa=isa)` function per recent [Intel® oneAPI Math Kernel Library (oneMKL)](https://www.intel.com/content/www/us/en/docs/onemkl/developer-guide-linux/2025-2/instruction-set-specific-dispatch-on-intel-archs.html) support.
69 |
70 | ## [2.3.0]
71 |
72 | Fixed CI to actually execute tests. Populated CBWR constants to match MKL headers.
73 |
74 | Added tests checking that `cbwr_set` and `cbwr_get` round-trip.
75 |
76 | ## [2.2.0]
77 |
78 | Closed issues #8, #7 and #5.
79 |
80 | Extended `mkl.cbwr_set` to recognize `'avx512_e1'`, `'avx512_mic_e1'`, as as strict conditional numerical reproducibility, supported via `'avx2,strict'`, `'avx512,strict'` (see [issue/8](http://github.com/IntelPython/mkl-service/issues/8)).
81 |
82 | Extended `mkl.cbwrt_get()` to mean `mkl.cbwr('all')`.
83 |
84 | ## [2.1.0]
85 |
86 | Change in setup script to not use `numpy.distutils` thus removing numpy as build-time dependency.
87 |
88 | Change in conda-recipe to allow conda build to build the recipe, but ignoring run export on mkl-service coming from mkl-devel metadata.
89 |
90 | ## [2.0.2]
91 |
92 | Correction to `setup.py` to not require Cython at the installation time.
93 |
94 | ## [2.0.1]
95 |
96 | Re-release, with some changes necessary for public CI builds to work.
97 |
98 | ## [2.0.0]
99 |
100 | Work-around for VS 9.0 not having `inline` keyword, allowing the package to build on Windows for Python 2.7
101 |
102 | ## [2.0.0]
103 |
104 | Rerelease of `mkl-service` package with version bumped to 2.0.0 to avoid version clash with `mkl-service` package from Anaconda.
105 |
106 | Improved argument checking, which raises an informative error.
107 |
108 | Loading the package with `import mkl` initializes Intel(R) MKL library to use LP64 interface (i.e. use of environment variable `MKL_INTERFACE` will not have effect).
109 |
110 | The choice of threading layer can be controlled with environment variable `MKL_THREADING_LAYER`. However the unset variable is interpreted differently that in Intel(R) MKL itself. If `mkl-service` detects that Gnu OpenMP has been loaded in Python space, the threading layer of Intle(R) MKL will be set to Gnu OpenMP, instead of Intel(R) OpenMP.
111 |
112 | ## [1.0.0]
113 |
114 | Initial release of `mkl-service` package.
115 |
--------------------------------------------------------------------------------
/mkl/_mkl_service.pxd:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2018, Intel Corporation
2 | #
3 | # Redistribution and use in source and binary forms, with or without
4 | # modification, are permitted provided that the following conditions are met:
5 | #
6 | # * Redistributions of source code must retain the above copyright notice,
7 | # this list of conditions and the following disclaimer.
8 | # * Redistributions in binary form must reproduce the above copyright
9 | # notice, this list of conditions and the following disclaimer in the
10 | # documentation and/or other materials provided with the distribution.
11 | # * Neither the name of Intel Corporation nor the names of its contributors
12 | # may be used to endorse or promote products derived from this software
13 | # without specific prior written permission.
14 | #
15 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16 | # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 | # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 | # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
19 | # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 | # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21 | # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
22 | # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
23 | # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24 | # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 |
26 |
27 | ctypedef long long MKL_INT64
28 | ctypedef unsigned long long MKL_UINT64
29 | ctypedef int MKL_INT
30 |
31 |
32 | cdef extern from "mkl.h":
33 | # MKL Function Domains Constants
34 | int MKL_DOMAIN_BLAS
35 | int MKL_DOMAIN_FFT
36 | int MKL_DOMAIN_VML
37 | int MKL_DOMAIN_PARDISO
38 | int MKL_DOMAIN_ALL
39 |
40 | # MKL Peak Memory Usage Constants
41 | int MKL_PEAK_MEM_ENABLE
42 | int MKL_PEAK_MEM_DISABLE
43 | int MKL_PEAK_MEM
44 | int MKL_PEAK_MEM_RESET
45 | int MKL_MEM_MCDRAM
46 |
47 | # CNR Control Constants
48 | int MKL_CBWR_BRANCH
49 | int MKL_CBWR_ALL
50 |
51 | int MKL_CBWR_STRICT
52 |
53 | int MKL_CBWR_OFF
54 | int MKL_CBWR_BRANCH_OFF
55 | int MKL_CBWR_AUTO
56 | int MKL_CBWR_COMPATIBLE
57 | int MKL_CBWR_SSE2
58 | int MKL_CBWR_SSSE3
59 | int MKL_CBWR_SSE4_1
60 | int MKL_CBWR_SSE4_2
61 | int MKL_CBWR_AVX
62 | int MKL_CBWR_AVX2
63 | int MKL_CBWR_AVX512_MIC
64 | int MKL_CBWR_AVX512
65 | int MKL_CBWR_AVX512_MIC_E1
66 | int MKL_CBWR_AVX512_E1
67 |
68 | int MKL_CBWR_SUCCESS
69 | int MKL_CBWR_ERR_INVALID_SETTINGS
70 | int MKL_CBWR_ERR_INVALID_INPUT
71 | int MKL_CBWR_ERR_UNSUPPORTED_BRANCH
72 | int MKL_CBWR_ERR_UNKNOWN_BRANCH
73 | int MKL_CBWR_ERR_MODE_CHANGE_FAILURE
74 |
75 | # ISA Constants
76 | int MKL_SINGLE_PATH_ENABLE
77 | int MKL_ENABLE_AVX512_E2
78 | int MKL_ENABLE_AVX512_E3
79 | int MKL_ENABLE_AVX512_E4
80 | int MKL_ENABLE_AVX512_MIC_E1
81 | int MKL_ENABLE_AVX512_E1
82 | int MKL_ENABLE_AVX512
83 | int MKL_ENABLE_AVX512_MIC
84 | int MKL_ENABLE_AVX2
85 | int MKL_ENABLE_AVX2_E1
86 | int MKL_ENABLE_AVX
87 | int MKL_ENABLE_SSE4_2
88 |
89 | # MPI Implementation Constants
90 | int MKL_BLACS_CUSTOM
91 | int MKL_BLACS_MSMPI
92 | int MKL_BLACS_INTELMPI
93 | int MKL_BLACS_MPICH2
94 | int MKL_BLACS_LASTMPI
95 |
96 | # VML Constants
97 | int VML_HA
98 | int VML_LA
99 | int VML_EP
100 | int VML_FTZDAZ_ON
101 | int VML_FTZDAZ_OFF
102 | int VML_ERRMODE_IGNORE
103 | int VML_ERRMODE_ERRNO
104 | int VML_ERRMODE_STDERR
105 | int VML_ERRMODE_EXCEPT
106 | int VML_ERRMODE_CALLBACK
107 | int VML_ERRMODE_DEFAULT
108 | int VML_STATUS_OK
109 | int VML_STATUS_ACCURACYWARNING
110 | int VML_STATUS_BADSIZE
111 | int VML_STATUS_BADMEM
112 | int VML_STATUS_ERRDOM
113 | int VML_STATUS_SING
114 | int VML_STATUS_OVERFLOW
115 | int VML_STATUS_UNDERFLOW
116 | int VML_ACCURACY_MASK
117 | int VML_FTZDAZ_MASK
118 | int VML_ERRMODE_MASK
119 |
120 | ctypedef struct MKLVersion:
121 | int MajorVersion
122 | int MinorVersion
123 | int UpdateVersion
124 | char* ProductStatus
125 | char* Build
126 | char* Processor
127 | char* Platform
128 |
129 | # MKL support functions
130 | void mkl_get_version(MKLVersion* pv)
131 | void mkl_get_version_string(char* buf, int len)
132 |
133 | # Threading
134 | void mkl_set_num_threads(int nth)
135 | int mkl_domain_set_num_threads(int nt, int domain)
136 | int mkl_set_num_threads_local(int nth)
137 | void mkl_set_dynamic(int flag)
138 | int mkl_get_max_threads()
139 | int mkl_domain_get_max_threads(int domain)
140 | int mkl_get_dynamic()
141 | int mkl_get_num_stripes()
142 | void mkl_set_num_stripes(int)
143 |
144 | # Timing
145 | float second()
146 | double dsecnd()
147 | void mkl_get_cpu_clocks(MKL_UINT64* clocks)
148 | double mkl_get_cpu_frequency()
149 | double mkl_get_max_cpu_frequency()
150 | double mkl_get_clocks_frequency()
151 |
152 | # Memory
153 | void mkl_free_buffers()
154 | void mkl_thread_free_buffers()
155 | int mkl_disable_fast_mm()
156 | MKL_INT64 mkl_mem_stat(int* buf)
157 | MKL_INT64 mkl_peak_mem_usage(int mode)
158 | int mkl_set_memory_limit(int mem_type, size_t limit)
159 |
160 | # Conditional Numerical Reproducibility
161 | int mkl_cbwr_set(int settings)
162 | int mkl_cbwr_get(int option)
163 | int mkl_cbwr_get_auto_branch()
164 |
165 | # Miscellaneous
166 | int mkl_enable_instructions(int isa)
167 | int mkl_set_env_mode(int mode)
168 | int mkl_verbose(int enable)
169 | int mkl_set_mpi(int vendor, const char* custom_library_name)
170 |
171 | # VM Service Functions
172 | unsigned int vmlSetMode(unsigned int mode)
173 | unsigned int vmlGetMode()
174 | int vmlSetErrStatus(const MKL_INT status)
175 | int vmlGetErrStatus()
176 | int vmlClearErrStatus()
177 |
--------------------------------------------------------------------------------
/mkl/_mklinitmodule.c:
--------------------------------------------------------------------------------
1 | /* -*- c -*- */
2 |
3 | /*
4 | * This is a dummy module whose purpose is to get distutils to generate the
5 | * configuration files before the libraries are made.
6 | */
7 |
8 | #if (defined(USING_MKL_RT) && defined(__linux__))
9 | #define FORCE_PRELOADING 1
10 | #define _GNU_SOURCE 1
11 | #include
12 | #include
13 | #include
14 | #undef _GNU_SOURCE
15 | #endif
16 |
17 | #include
18 | #if PY_MAJOR_VERSION >= 3
19 | #define IS_PY3K
20 | #endif
21 | #include "mkl.h"
22 |
23 | static struct PyMethodDef methods[] = {{NULL, NULL, 0, NULL}};
24 |
25 | #if defined(_MSC_VER) && (_MSC_VER <= 1500)
26 | #define MKL_SERVICE_INLINE
27 | #else
28 | #define MKL_SERVICE_INLINE inline
29 | #endif
30 |
31 | static MKL_SERVICE_INLINE void _set_mkl_ilp64(void);
32 | static MKL_SERVICE_INLINE void _set_mkl_lp64(void);
33 | static MKL_SERVICE_INLINE void _set_mkl_interface(void);
34 |
35 | static const char *mtlayer;
36 | static const char *verbose;
37 |
38 | #if FORCE_PRELOADING
39 | #define VERBOSE(...) \
40 | if (verbose) \
41 | printf("mkl-service + Intel(R) MKL: " __VA_ARGS__)
42 |
43 | static void restore_mtlayer(void) {
44 | if (mtlayer) {
45 | VERBOSE(
46 | "Re-setting Intel(R) MKL_THREADING_LAYER=%s for the forked process\n",
47 | mtlayer);
48 | setenv("MKL_THREADING_LAYER", mtlayer, 1);
49 | } else {
50 | VERBOSE("Unsetting Intel(R) MKL_THREADING_LAYER variable for the forked "
51 | "process \n");
52 | unsetenv("MKL_THREADING_LAYER");
53 | }
54 | }
55 | #endif
56 |
57 | static void _preload_threading_layer(void) {
58 | #if FORCE_PRELOADING
59 | #define SET_MTLAYER(L) \
60 | do { \
61 | VERBOSE("setting Intel(R) MKL to use " #L " OpenMP runtime\n"); \
62 | mkl_set_threading_layer(MKL_THREADING_##L); \
63 | setenv("MKL_THREADING_LAYER", #L, 0); \
64 | pthread_atfork(NULL, NULL, &restore_mtlayer); \
65 | } while (0)
66 | #define PRELOAD(lib) \
67 | do { \
68 | VERBOSE("preloading %s runtime\n", lib); \
69 | dlopen(lib, RTLD_LAZY | RTLD_GLOBAL); \
70 | } while (0)
71 | /*
72 | * The following is the pseudo-code skeleton for reinterpreting unset
73 | * MKL_THREADING_LAYER
74 | *
75 | * if MKL_THREADING_LAYER is empty
76 | * if kmp_calloc (or a suitable symbol identified by Terry) is
77 | * loaded, we are using Intel(R) OpenMP, i.e. reinterpret as implicit value of
78 | * INTEL otherwise check if other Open MP is loaded by checking
79 | * get_omp_num_threads symbol if not loaded: assume INTEL, and force loading
80 | * of IOMP5 if loaded: if Gnu OMP, set MKL_THREADING_LAYER=GNU, and call
81 | * set_mkl_threading_layer(MKL_THREADING_GNU) if other vendors? if
82 | * MKL_THREADING_LAYER is INTEL force loading of iomp, to preempt possibility
83 | * of other modules loading other OMP library before MKL is actually used
84 | *
85 | * should we treat other possible values of MKL_THREADING_LAYER
86 | * specially?
87 | *
88 | */
89 |
90 | const char *libiomp = "libiomp5.so";
91 | verbose = getenv("MKL_VERBOSE");
92 | mtlayer = getenv("MKL_THREADING_LAYER");
93 |
94 | /* Use of RTLD_DEFAULT handler is to indicate that symbol is being lookup-up
95 | * among symbols presently known to this process.
96 | *
97 | * See: https://pubs.opengroup.org/onlinepubs/9699919799/functions/dlsym.html
98 | */
99 | void *omp = dlsym(RTLD_DEFAULT, "omp_get_num_threads");
100 | const char *omp_name = "(unidentified)";
101 | const char *iomp = NULL; /* non-zero indicates Intel(R) OpenMP is loaded */
102 | Dl_info omp_info;
103 |
104 | if (verbose && (verbose[0] == 0 || atoi(verbose) == 0))
105 | verbose = NULL;
106 |
107 | VERBOSE("THREADING LAYER: %s\n", mtlayer);
108 |
109 | if (omp) {
110 | if (dladdr(omp, &omp_info)) {
111 | omp_name = basename(
112 | omp_info.dli_fname); /* GNU version doesn't modify argument */
113 | iomp = strstr(omp_name, libiomp);
114 | }
115 | VERBOSE("%s OpenMP runtime %s is already loaded\n",
116 | iomp ? "Intel(R)" : "Other vendor", omp_name);
117 | }
118 | if (!mtlayer || mtlayer[0] == 0) { /* unset or empty */
119 | if (omp) { /* if OpenMP runtime is loaded */
120 | if (iomp) /* if Intel runtime is loaded */
121 | SET_MTLAYER(INTEL);
122 | else /* otherwise, assume it is GNU OpenMP */
123 | SET_MTLAYER(GNU);
124 | } else { /* nothing is loaded */
125 | SET_MTLAYER(INTEL);
126 | PRELOAD(libiomp);
127 | }
128 | } else if (strcasecmp(mtlayer, "intel") ==
129 | 0) { /* Intel runtime is requested */
130 | if (omp && !iomp) {
131 | fprintf(stderr,
132 | "Error: mkl-service + Intel(R) MKL: MKL_THREADING_LAYER=INTEL is "
133 | "incompatible with %s library."
134 | "\n\tTry to import numpy first or set the threading layer "
135 | "accordingly. "
136 | "Set MKL_SERVICE_FORCE_INTEL to force it.\n",
137 | omp_name);
138 | if (!getenv("MKL_SERVICE_FORCE_INTEL"))
139 | exit(1);
140 | } else
141 | PRELOAD(libiomp);
142 | }
143 | #endif
144 | return;
145 | }
146 |
147 | static MKL_SERVICE_INLINE void _set_mkl_ilp64(void) {
148 | #ifdef USING_MKL_RT
149 | mkl_set_interface_layer(MKL_INTERFACE_ILP64);
150 | #endif
151 | return;
152 | }
153 |
154 | static MKL_SERVICE_INLINE void _set_mkl_lp64(void) {
155 | #ifdef USING_MKL_RT
156 | mkl_set_interface_layer(MKL_INTERFACE_LP64);
157 | #endif
158 | return;
159 | }
160 |
161 | static MKL_SERVICE_INLINE void _set_mkl_interface(void) {
162 | _set_mkl_lp64();
163 | _preload_threading_layer();
164 | }
165 |
166 | #if defined(IS_PY3K)
167 | static struct PyModuleDef moduledef = {PyModuleDef_HEAD_INIT,
168 | "mklinit",
169 | NULL,
170 | -1,
171 | methods,
172 | NULL,
173 | NULL,
174 | NULL,
175 | NULL};
176 | #endif
177 |
178 | /* Initialization function for the module */
179 | #if defined(IS_PY3K)
180 | PyMODINIT_FUNC PyInit__mklinit(void) {
181 | PyObject *m;
182 |
183 | _set_mkl_interface();
184 | m = PyModule_Create(&moduledef);
185 | if (!m) {
186 | return NULL;
187 | }
188 |
189 | return m;
190 | }
191 | #else
192 | PyMODINIT_FUNC init_mklinit(void) {
193 | _set_mkl_interface();
194 | Py_InitModule("_mklinit", methods);
195 | }
196 | #endif
197 |
--------------------------------------------------------------------------------
/mkl/tests/test_mkl_service.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2018, Intel Corporation
2 | #
3 | # Redistribution and use in source and binary forms, with or without
4 | # modification, are permitted provided that the following conditions are met:
5 | #
6 | # * Redistributions of source code must retain the above copyright notice,
7 | # this list of conditions and the following disclaimer.
8 | # * Redistributions in binary form must reproduce the above copyright
9 | # notice, this list of conditions and the following disclaimer in the
10 | # documentation and/or other materials provided with the distribution.
11 | # * Neither the name of Intel Corporation nor the names of its contributors
12 | # may be used to endorse or promote products derived from this software
13 | # without specific prior written permission.
14 | #
15 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16 | # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 | # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 | # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
19 | # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 | # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21 | # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
22 | # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
23 | # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24 | # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 |
26 | # pylint: disable=no-member
27 |
28 | import pytest
29 |
30 | import mkl
31 |
32 |
33 | def test_set_num_threads():
34 | saved = mkl.get_max_threads()
35 | half_nt = int((1 + saved) / 2)
36 | mkl.set_num_threads(half_nt)
37 | assert mkl.get_max_threads() == half_nt
38 | mkl.set_num_threads(saved)
39 |
40 |
41 | def test_domain_set_num_threads_blas():
42 | saved_blas_nt = mkl.domain_get_max_threads(domain="blas")
43 | saved_fft_nt = mkl.domain_get_max_threads(domain="fft")
44 | saved_vml_nt = mkl.domain_get_max_threads(domain="vml")
45 | # set
46 | blas_nt = int((3 + saved_blas_nt) / 4)
47 | fft_nt = int((3 + 2 * saved_fft_nt) / 4)
48 | vml_nt = int((3 + 3 * saved_vml_nt) / 4)
49 | status = mkl.domain_set_num_threads(blas_nt, domain="blas")
50 | assert status == "success"
51 | status = mkl.domain_set_num_threads(fft_nt, domain="fft")
52 | assert status == "success"
53 | status = mkl.domain_set_num_threads(vml_nt, domain="vml")
54 | assert status == "success"
55 | # check
56 | assert mkl.domain_get_max_threads(domain="blas") == blas_nt
57 | assert mkl.domain_get_max_threads(domain="fft") == fft_nt
58 | assert mkl.domain_get_max_threads(domain="vml") == vml_nt
59 | # restore
60 | status = mkl.domain_set_num_threads(saved_blas_nt, domain="blas")
61 | assert status == "success"
62 | status = mkl.domain_set_num_threads(saved_fft_nt, domain="fft")
63 | assert status == "success"
64 | status = mkl.domain_set_num_threads(saved_vml_nt, domain="vml")
65 | assert status == "success"
66 |
67 |
68 | def test_domain_set_num_threads_fft():
69 | status = mkl.domain_set_num_threads(4, domain="fft")
70 | assert status == "success"
71 |
72 |
73 | def test_domain_set_num_threads_vml():
74 | status = mkl.domain_set_num_threads(4, domain="vml")
75 | assert status == "success"
76 |
77 |
78 | def test_domain_set_num_threads_pardiso():
79 | status = mkl.domain_set_num_threads(4, domain="pardiso")
80 | assert status == "success"
81 |
82 |
83 | def test_domain_set_num_threads_all():
84 | status = mkl.domain_set_num_threads(4, domain="all")
85 | assert status == "success"
86 |
87 |
88 | def test_set_num_threads_local():
89 | mkl.set_num_threads(1)
90 | status = mkl.set_num_threads_local(2)
91 | assert status == "global_num_threads"
92 | status = mkl.set_num_threads_local(4)
93 | assert status == 2
94 | status = mkl.set_num_threads_local(0)
95 | assert status == 4
96 | status = mkl.set_num_threads_local(8)
97 | assert status == "global_num_threads"
98 |
99 |
100 | def test_set_dynamic():
101 | mkl.set_dynamic(True)
102 |
103 |
104 | def test_get_max_threads():
105 | mkl.get_max_threads()
106 |
107 |
108 | def test_domain_get_max_threads_blas():
109 | mkl.domain_get_max_threads(domain="blas")
110 |
111 |
112 | def test_domain_get_max_threads_fft():
113 | mkl.domain_get_max_threads(domain="fft")
114 |
115 |
116 | def test_domain_get_max_threads_vml():
117 | mkl.domain_get_max_threads(domain="vml")
118 |
119 |
120 | def test_domain_get_max_threads_pardiso():
121 | mkl.domain_get_max_threads(domain="pardiso")
122 |
123 |
124 | def test_domain_get_max_threads_all():
125 | mkl.domain_get_max_threads(domain="all")
126 |
127 |
128 | def test_get_dynamic():
129 | mkl.get_dynamic()
130 |
131 |
132 | # https://software.intel.com/en-us/mkl-developer-reference-c-timing
133 | def test_second():
134 | s1 = mkl.second()
135 | s2 = mkl.second()
136 | delta = s2 - s1
137 | assert delta >= 0
138 |
139 |
140 | def test_dsecnd():
141 | d1 = mkl.dsecnd()
142 | d2 = mkl.dsecnd()
143 | delta = d2 - d1
144 | assert delta >= 0
145 |
146 |
147 | def test_get_cpu_clocks():
148 | c1 = mkl.get_cpu_clocks()
149 | c2 = mkl.get_cpu_clocks()
150 | delta = c2 - c1
151 | assert delta >= 0
152 |
153 |
154 | def test_get_cpu_frequency():
155 | assert mkl.get_cpu_frequency() >= 0
156 |
157 |
158 | def test_get_max_cpu_frequency():
159 | assert mkl.get_max_cpu_frequency() >= 0
160 |
161 |
162 | def test_get_clocks_frequency():
163 | assert mkl.get_clocks_frequency() >= 0
164 |
165 |
166 | def test_free_buffers():
167 | mkl.free_buffers()
168 |
169 |
170 | def test_thread_free_buffers():
171 | mkl.thread_free_buffers()
172 |
173 |
174 | def test_disable_fast_mm():
175 | mkl.disable_fast_mm()
176 |
177 |
178 | def test_mem_stat():
179 | mkl.mem_stat()
180 |
181 |
182 | def test_peak_mem_usage_enable():
183 | mkl.peak_mem_usage("enable")
184 |
185 |
186 | def test_peak_mem_usage_disable():
187 | mkl.peak_mem_usage("disable")
188 |
189 |
190 | def test_peak_mem_usage_peak_mem():
191 | mkl.peak_mem_usage("peak_mem")
192 |
193 |
194 | def test_peak_mem_usage_peak_mem_reset():
195 | mkl.peak_mem_usage("peak_mem_reset")
196 |
197 |
198 | def test_set_memory_limit():
199 | mkl.set_memory_limit(2**16)
200 |
201 |
202 | def check_cbwr(branch, cnr_const):
203 | status = mkl.cbwr_set(branch=branch)
204 | if status == "success":
205 | expected_value = "branch_off" if branch == "off" else branch
206 | actual_value = mkl.cbwr_get(cnr_const=cnr_const)
207 | assert (
208 | actual_value == expected_value
209 | ), f"Round-trip failure for CNR branch '{branch}', CNR const '{cnr_const}"
210 | elif status not in ["err_unsupported_branch", "err_mode_change_failure"]:
211 | # if MKL has been initialized already,
212 | # setting CBWR will error with mode_change_failure
213 | pytest.fail(status)
214 |
215 |
216 | branches = [
217 | "off",
218 | "branch_off",
219 | "auto",
220 | "compatible",
221 | "sse2",
222 | "ssse3",
223 | "sse4_1",
224 | "sse4_2",
225 | "avx",
226 | "avx2",
227 | "avx512_mic",
228 | "avx512",
229 | "avx512_mic_e1",
230 | "avx512_e1",
231 | ]
232 |
233 |
234 | strict = [
235 | "avx2,strict",
236 | "avx512_mic,strict",
237 | "avx512,strict",
238 | "avx512_e1,strict",
239 | ]
240 |
241 |
242 | @pytest.mark.parametrize("branch", branches)
243 | def test_cbwr_branch(branch):
244 | check_cbwr(branch, "branch")
245 |
246 |
247 | @pytest.mark.parametrize("branch", branches + strict)
248 | def test_cbwr_all(branch):
249 | check_cbwr(branch, "all")
250 |
251 |
252 | def test_cbwr_get_auto_branch():
253 | mkl.cbwr_get_auto_branch()
254 |
255 |
256 | def test_enable_instructions_avx512_mic_e1():
257 | mkl.enable_instructions("avx512_mic_e1")
258 |
259 |
260 | def test_enable_instructions_avx512():
261 | mkl.enable_instructions("avx512")
262 |
263 |
264 | def test_enable_instructions_avx512_mic():
265 | mkl.enable_instructions("avx512_mic")
266 |
267 |
268 | def test_enable_instructions_avx2():
269 | mkl.enable_instructions("avx2")
270 |
271 |
272 | def test_enable_instructions_avx():
273 | mkl.enable_instructions("avx")
274 |
275 |
276 | def test_enable_instructions_sse4_2():
277 | mkl.enable_instructions("sse4_2")
278 |
279 |
280 | def test_set_env_mode():
281 | mkl.set_env_mode()
282 |
283 |
284 | def test_get_env_mode():
285 | mkl.get_env_mode()
286 |
287 |
288 | def test_verbose_false():
289 | mkl.verbose(False)
290 |
291 |
292 | def test_verbose_true():
293 | mkl.verbose(True)
294 |
295 |
296 | @pytest.mark.skip(reason="Skipping MPI-related test")
297 | def test_set_mpi_custom():
298 | mkl.set_mpi("custom", "custom_library_name")
299 |
300 |
301 | @pytest.mark.skip(reason="Skipping MPI-related test")
302 | def test_set_mpi_msmpi():
303 | mkl.set_mpi("msmpi")
304 |
305 |
306 | @pytest.mark.skip(reason="Skipping MPI-related test")
307 | def test_set_mpi_intelmpi():
308 | mkl.set_mpi("intelmpi")
309 |
310 |
311 | @pytest.mark.skip(reason="Skipping MPI-related test")
312 | def test_set_mpi_mpich2():
313 | mkl.set_mpi("mpich2")
314 |
315 |
316 | def test_vml_set_get_mode_roundtrip():
317 | saved = mkl.vml_get_mode()
318 | mkl.vml_set_mode(*saved) # should not raise errors
319 |
320 |
321 | def test_vml_set_mode_ha_on_ignore():
322 | mkl.vml_set_mode("ha", "on", "ignore")
323 |
324 |
325 | def test_vml_set_mode_ha_on_errno():
326 | mkl.vml_set_mode("ha", "on", "errno")
327 |
328 |
329 | def test_vml_set_mode_la_on_stderr():
330 | mkl.vml_set_mode("la", "on", "stderr")
331 |
332 |
333 | def test_vml_set_mode_la_off_except():
334 | mkl.vml_set_mode("la", "off", "except")
335 |
336 |
337 | def test_vml_set_mode_op_off_callback():
338 | mkl.vml_set_mode("ep", "off", "callback")
339 |
340 |
341 | def test_vml_set_mode_ep_off_default():
342 | mkl.vml_set_mode("ep", "off", "default")
343 |
344 |
345 | def test_vml_get_mode():
346 | mkl.vml_get_mode()
347 |
348 |
349 | def test_vml_set_err_status_ok():
350 | mkl.vml_set_err_status("ok")
351 |
352 |
353 | def test_vml_set_err_status_accuracywarning():
354 | mkl.vml_set_err_status("accuracywarning")
355 |
356 |
357 | def test_vml_set_err_status_badsize():
358 | mkl.vml_set_err_status("badsize")
359 |
360 |
361 | def test_vml_set_err_status_badmem():
362 | mkl.vml_set_err_status("badmem")
363 |
364 |
365 | def test_vml_set_err_status_errdom():
366 | mkl.vml_set_err_status("errdom")
367 |
368 |
369 | def test_vml_set_err_status_sing():
370 | mkl.vml_set_err_status("sing")
371 |
372 |
373 | def test_vml_set_err_status_overflow():
374 | mkl.vml_set_err_status("overflow")
375 |
376 |
377 | def test_vml_set_err_status_underflow():
378 | mkl.vml_set_err_status("underflow")
379 |
380 |
381 | def test_vml_get_err_status():
382 | mkl.vml_get_err_status()
383 |
384 |
385 | def test_vml_clear_err_status():
386 | mkl.vml_clear_err_status()
387 |
388 |
389 | def test_get_version():
390 | """
391 | Version info sets mode of MKL library, such as
392 | instruction pathways and conditional numerical
393 | reproducibility regime. This test is moved to
394 | the bottom to allow proper testing of functions
395 | controllign those.
396 | """
397 | v = mkl.get_version()
398 | assert isinstance(v, dict)
399 | assert "MajorVersion" in v
400 | assert "MinorVersion" in v
401 | assert "UpdateVersion" in v
402 |
403 |
404 | def test_get_version_string():
405 | v = mkl.get_version_string()
406 | assert isinstance(v, str)
407 | assert "Math Kernel Library" in v
408 |
--------------------------------------------------------------------------------
/.github/workflows/conda-package.yml:
--------------------------------------------------------------------------------
1 | name: Conda package
2 |
3 | on:
4 | push:
5 | branches:
6 | - master
7 | pull_request:
8 |
9 | permissions: read-all
10 |
11 | env:
12 | PACKAGE_NAME: mkl-service
13 | MODULE_NAME: mkl
14 | TEST_ENV_NAME: test_mkl_service
15 | VER_SCRIPT1: "import json; f = open('ver.json', 'r'); j = json.load(f); f.close(); "
16 | VER_SCRIPT2: "d = j['mkl-service'][0]; print('='.join((d[s] for s in ('version', 'build'))))"
17 |
18 | jobs:
19 | build_linux:
20 | runs-on: ubuntu-latest
21 |
22 | strategy:
23 | matrix:
24 | python: ['3.10', '3.11', '3.12', '3.13', '3.14']
25 |
26 | steps:
27 | - name: Cancel Previous Runs
28 | uses: styfle/cancel-workflow-action@85880fa0301c86cca9da44039ee3bb12d3bedbfa # 0.12.1
29 | with:
30 | access_token: ${{ github.token }}
31 |
32 | - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
33 | with:
34 | fetch-depth: 0
35 |
36 | - name: Set pkgs_dirs
37 | run: |
38 | echo "pkgs_dirs: [~/.conda/pkgs]" >> ~/.condarc
39 |
40 | - name: Cache conda packages
41 | uses: actions/cache@9255dc7a253b0ccc959486e2bca901246202afeb # v5.0.1
42 | env:
43 | CACHE_NUMBER: 0 # Increase to reset cache
44 | with:
45 | path: ~/.conda/pkgs
46 | key:
47 | ${{ runner.os }}-conda-${{ env.CACHE_NUMBER }}-python-${{ matrix.python }}-${{hashFiles('**/meta.yaml') }}
48 | restore-keys: |
49 | ${{ runner.os }}-conda-${{ env.CACHE_NUMBER }}-python-${{ matrix.python }}-
50 | ${{ runner.os }}-conda-${{ env.CACHE_NUMBER }}-
51 |
52 | - name: Add conda to system path
53 | run: echo $CONDA/bin >> $GITHUB_PATH
54 |
55 | - name: Install conda-build
56 | run: conda install conda-build
57 |
58 | - name: Store conda paths as envs
59 | shell: bash -el {0}
60 | run: |
61 | echo "CONDA_BLD=/usr/share/miniconda/conda-bld/linux-64/" >> $GITHUB_ENV
62 | echo "WHEELS_OUTPUT_FOLDER=$GITHUB_WORKSPACE/" >> $GITHUB_ENV
63 |
64 | - name: Build conda package
65 | run: |
66 | CHANNELS="-c conda-forge -c conda-forge/label/python_rc -c https://software.repos.intel.com/python/conda --override-channels"
67 | VERSIONS="--python ${{ matrix.python }}"
68 | TEST="--no-test"
69 |
70 | conda build \
71 | $TEST \
72 | $VERSIONS \
73 | $CHANNELS \
74 | conda-recipe
75 |
76 | - name: Upload artifact
77 | uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
78 | with:
79 | name: ${{ env.PACKAGE_NAME }} ${{ runner.os }} Python ${{ matrix.python }}
80 | path: ${{ env.CONDA_BLD }}${{ env.PACKAGE_NAME }}-*.conda
81 |
82 | - name: Upload wheels artifact
83 | uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
84 | with:
85 | name: ${{ env.PACKAGE_NAME }} ${{ runner.os }} Wheels Python ${{ matrix.python }}
86 | path: ${{ env.WHEELS_OUTPUT_FOLDER }}mkl_service-*.whl
87 |
88 | build_windows:
89 | runs-on: windows-latest
90 |
91 | strategy:
92 | matrix:
93 | python: ['3.10', '3.11', '3.12', '3.13', '3.14']
94 |
95 | steps:
96 | - name: Cancel Previous Runs
97 | uses: styfle/cancel-workflow-action@85880fa0301c86cca9da44039ee3bb12d3bedbfa # 0.12.1
98 | with:
99 | access_token: ${{ github.token }}
100 |
101 | - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
102 | with:
103 | fetch-depth: 0
104 | - uses: conda-incubator/setup-miniconda@835234971496cad1653abb28a638a281cf32541f # v3.2.0
105 | with:
106 | miniforge-version: latest
107 | use-mamba: 'true'
108 | conda-remove-defaults: 'true'
109 | activate-environment: 'build'
110 | python-version: '3.13' # no python 3.14 support by conda-build
111 |
112 | - name: Cache conda packages
113 | uses: actions/cache@9255dc7a253b0ccc959486e2bca901246202afeb # v5.0.1
114 | env:
115 | CACHE_NUMBER: 3 # Increase to reset cache
116 | with:
117 | path: /home/runner/conda_pkgs_dir
118 | key:
119 | ${{ runner.os }}-conda-${{ env.CACHE_NUMBER }}-python-${{ matrix.python }}-${{hashFiles('**/meta.yaml') }}
120 | restore-keys: |
121 | ${{ runner.os }}-conda-${{ env.CACHE_NUMBER }}-python-${{ matrix.python }}-
122 | ${{ runner.os }}-conda-${{ env.CACHE_NUMBER }}-
123 |
124 | - name: Install conda-build
125 | run: conda install conda-build
126 |
127 | - name: Store conda paths as envs
128 | shell: bash -el {0}
129 | run: |
130 | echo "CONDA_BLD=$CONDA_PREFIX\\conda-bld\\win-64\\" >> $GITHUB_ENV
131 | echo "WHEELS_OUTPUT_FOLDER=$GITHUB_WORKSPACE\\" >> $GITHUB_ENV
132 |
133 | - name: Build conda package
134 | run: conda build --no-test --python ${{ matrix.python }} -c https://software.repos.intel.com/python/conda -c conda-forge -c conda-forge/label/python_rc --override-channels conda-recipe
135 |
136 | - name: Upload artifact
137 | uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
138 | with:
139 | name: ${{ env.PACKAGE_NAME }} ${{ runner.os }} Python ${{ matrix.python }}
140 | path: ${{ env.CONDA_BLD }}${{ env.PACKAGE_NAME }}-*.conda
141 |
142 | - name: Upload wheels artifact
143 | uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
144 | with:
145 | name: ${{ env.PACKAGE_NAME }} ${{ runner.os }} Wheels Python ${{ matrix.python }}
146 | path: ${{ env.WHEELS_OUTPUT_FOLDER }}mkl_service-*.whl
147 |
148 | test_linux:
149 | needs: build_linux
150 | runs-on: ${{ matrix.runner }}
151 |
152 | strategy:
153 | matrix:
154 | python: ['3.10', '3.11', '3.12', '3.13', '3.14']
155 | experimental: [false]
156 | runner: [ubuntu-latest]
157 | continue-on-error: ${{ matrix.experimental }}
158 | env:
159 | CHANNELS: -c conda-forge -c conda-forge/label/python_rc -c https://software.repos.intel.com/python/conda --override-channels
160 |
161 | steps:
162 | - name: Download artifact
163 | uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0
164 | with:
165 | name: ${{ env.PACKAGE_NAME }} ${{ runner.os }} Python ${{ matrix.python }}
166 |
167 | - name: Add conda to system path
168 | run: echo $CONDA/bin >> $GITHUB_PATH
169 |
170 | - name: Install conda-build
171 | run: conda install conda-build
172 |
173 | - name: Create conda channel
174 | run: |
175 | mkdir -p $GITHUB_WORKSPACE/channel/linux-64
176 | conda index $GITHUB_WORKSPACE/channel || exit 1
177 | mv ${PACKAGE_NAME}-*.conda $GITHUB_WORKSPACE/channel/linux-64 || exit 1
178 | conda index $GITHUB_WORKSPACE/channel || exit 1
179 | # Test channel
180 | conda search $PACKAGE_NAME -c $GITHUB_WORKSPACE/channel --override-channels --info --json > $GITHUB_WORKSPACE/ver.json
181 | cat ver.json
182 |
183 | - name: Collect dependencies
184 | run: |
185 | . $CONDA/etc/profile.d/conda.sh
186 | CHANNELS="-c $GITHUB_WORKSPACE/channel ${{ env.CHANNELS }}"
187 | export PACKAGE_VERSION=$(python -c "${VER_SCRIPT1} ${VER_SCRIPT2}")
188 | conda create -n ${{ env.TEST_ENV_NAME }} $PACKAGE_NAME=${PACKAGE_VERSION} python=${{ matrix.python }} $CHANNELS --only-deps --dry-run > lockfile
189 | cat lockfile
190 |
191 | - name: Set pkgs_dirs
192 | run: |
193 | echo "pkgs_dirs: [~/.conda/pkgs]" >> ~/.condarc
194 |
195 | - name: Cache conda packages
196 | uses: actions/cache@9255dc7a253b0ccc959486e2bca901246202afeb # v5.0.1
197 | env:
198 | CACHE_NUMBER: 0 # Increase to reset cache
199 | with:
200 | path: ~/.conda/pkgs
201 | key:
202 | ${{ runner.os }}-conda-${{ env.CACHE_NUMBER }}-python-${{ matrix.python }}-${{hashFiles('lockfile') }}
203 | restore-keys: |
204 | ${{ runner.os }}-conda-${{ env.CACHE_NUMBER }}-python-${{ matrix.python }}-
205 | ${{ runner.os }}-conda-${{ env.CACHE_NUMBER }}-
206 |
207 | - name: Install mkl-service
208 | run: |
209 | . $CONDA/etc/profile.d/conda.sh
210 | CHANNELS="-c $GITHUB_WORKSPACE/channel ${{ env.CHANNELS }}"
211 | export PACKAGE_VERSION=$(python -c "${VER_SCRIPT1} ${VER_SCRIPT2}")
212 | conda create -n ${{ env.TEST_ENV_NAME }} $PACKAGE_NAME=${PACKAGE_VERSION} pytest python=${{ matrix.python }} $CHANNELS
213 | # Test installed packages
214 | conda list
215 |
216 | - name: Run tests
217 | run: |
218 | . $CONDA/etc/profile.d/conda.sh
219 | conda activate ${{ env.TEST_ENV_NAME }}
220 | pytest -vv --pyargs ${{ env.MODULE_NAME }}
221 |
222 | test_windows:
223 | needs: build_windows
224 | runs-on: ${{ matrix.runner }}
225 |
226 | strategy:
227 | matrix:
228 | python: ['3.10', '3.11', '3.12', '3.13', '3.14']
229 | experimental: [false]
230 | runner: [windows-latest]
231 | continue-on-error: ${{ matrix.experimental }}
232 | env:
233 | CHANNELS: -c conda-forge -c conda-forge/label/python_rc -c https://software.repos.intel.com/python/conda --override-channels
234 |
235 | steps:
236 | - name: Download artifact
237 | uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0
238 | with:
239 | name: ${{ env.PACKAGE_NAME }} ${{ runner.os }} Python ${{ matrix.python }}
240 | - uses: conda-incubator/setup-miniconda@835234971496cad1653abb28a638a281cf32541f # v3.2.0
241 | with:
242 | miniforge-version: latest
243 | use-mamba: 'true'
244 | conda-remove-defaults: 'true'
245 | activate-environment: 'test'
246 | python-version: '3.13' # no python 3.14 support by conda-index
247 |
248 | - name: Install conda-index
249 | run: conda install conda-index
250 |
251 | - name: Create conda channel
252 | run: |
253 | mkdir ${{ env.GITHUB_WORKSPACE }}\channel\win-64
254 | move ${{ env.PACKAGE_NAME }}-*.conda ${{ env.GITHUB_WORKSPACE }}\channel\win-64
255 | python -m conda_index ${{ env.GITHUB_WORKSPACE }}/channel
256 |
257 | # Test channel
258 | conda search ${{ env.PACKAGE_NAME }} -c ${{ env.GITHUB_WORKSPACE }}/channel --override-channels --info --json > ${{ env.GITHUB_WORKSPACE }}\ver.json
259 | more ${{ env.GITHUB_WORKSPACE }}\ver.json
260 |
261 | - name: Collect dependencies
262 | shell: cmd
263 | run: |
264 | @ECHO ON
265 | copy /Y ${{ env.GITHUB_WORKSPACE }}\ver.json .
266 | set "SCRIPT=%VER_SCRIPT1% %VER_SCRIPT2%"
267 | FOR /F "tokens=* USEBACKQ" %%F IN (`python -c "%SCRIPT%"`) DO (
268 | SET PACKAGE_VERSION=%%F
269 | )
270 | conda create -n ${{ env.TEST_ENV_NAME }} ${{ env.PACKAGE_NAME }}=%PACKAGE_VERSION% python=${{ matrix.python }} -c ${{ env.GITHUB_WORKSPACE }}/channel ${{ env.CHANNELS }} --only-deps --dry-run > lockfile
271 | more lockfile
272 |
273 | - name: Cache conda packages
274 | uses: actions/cache@9255dc7a253b0ccc959486e2bca901246202afeb # v5.0.1
275 | env:
276 | CACHE_NUMBER: 3 # Increase to reset cache
277 | with:
278 | path: /home/runner/conda_pkgs_dir
279 | key:
280 | ${{ runner.os }}-conda-${{ env.CACHE_NUMBER }}-python-${{ matrix.python }}-${{hashFiles('lockfile') }}
281 | restore-keys: |
282 | ${{ runner.os }}-conda-${{ env.CACHE_NUMBER }}-python-${{ matrix.python }}-
283 | ${{ runner.os }}-conda-${{ env.CACHE_NUMBER }}-
284 |
285 | # add intel-openmp as an explicit dependency
286 | # to avoid it being missed when package version is specified exactly
287 | - name: Install mkl-service
288 | shell: cmd
289 | run: |
290 | @ECHO ON
291 | copy /Y ${{ env.GITHUB_WORKSPACE }}\ver.json .
292 | set "SCRIPT=%VER_SCRIPT1% %VER_SCRIPT2%"
293 | FOR /F "tokens=* USEBACKQ" %%F IN (`python -c "%SCRIPT%"`) DO (
294 | SET PACKAGE_VERSION=%%F
295 | )
296 | SET "WORKAROUND_DEPENDENCIES=intel-openmp"
297 | conda create -n ${{ env.TEST_ENV_NAME }} ${{ env.PACKAGE_NAME }}=%PACKAGE_VERSION% %WORKAROUND_DEPENDENCIES% pytest python=${{ matrix.python }} -c ${{ env.GITHUB_WORKSPACE }}/channel ${{ env.CHANNELS }}
298 | # Test installed packages
299 | conda list
300 |
301 | - name: Run tests
302 | run: |
303 | conda activate -n ${{ env.TEST_ENV_NAME }}
304 | pytest -v --pyargs ${{ env.MODULE_NAME }}
305 |
--------------------------------------------------------------------------------
/mkl/_mkl_service.pyx:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2018, Intel Corporation
2 | #
3 | # Redistribution and use in source and binary forms, with or without
4 | # modification, are permitted provided that the following conditions are met:
5 | #
6 | # * Redistributions of source code must retain the above copyright notice,
7 | # this list of conditions and the following disclaimer.
8 | # * Redistributions in binary form must reproduce the above copyright
9 | # notice, this list of conditions and the following disclaimer in the
10 | # documentation and/or other materials provided with the distribution.
11 | # * Neither the name of Intel Corporation nor the names of its contributors
12 | # may be used to endorse or promote products derived from this software
13 | # without specific prior written permission.
14 | #
15 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16 | # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 | # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 | # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
19 | # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 | # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21 | # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
22 | # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
23 | # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24 | # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 |
26 | # distutils: language = c
27 | # cython: language_level=3
28 |
29 | import numbers
30 | import warnings
31 | cimport mkl._mkl_service as mkl
32 |
33 |
34 | cdef extern from *:
35 | """
36 | /* define MKL_BLACS_MPICH2 if undefined */
37 | #ifndef MKL_BLACS_MPICH2
38 | #define MKL_BLACS_MPICH2 -1
39 | #endif
40 | """
41 |
42 | ctypedef struct MemStatData:
43 | # DataAllocatedBytes, AllocatedBuffers
44 | mkl.MKL_INT64 allocated_bytes
45 | int allocated_buffers
46 |
47 |
48 | # Version Information
49 | cpdef get_version():
50 | """
51 | Returns the Intel(R) MKL version as a dictionary.
52 | """
53 | return __get_version()
54 |
55 |
56 | cpdef get_version_string():
57 | """
58 | Returns the Intel(R) MKL version as a string.
59 | """
60 | return __get_version_string()
61 |
62 |
63 | # Threading
64 | cpdef set_num_threads(num_threads):
65 | """
66 | Specifies the number of OpenMP* threads to use.
67 | """
68 | cdef int c_num_threads = __python_obj_to_int(num_threads, "set_num_threads")
69 | __check_positive_num_threads(c_num_threads, "set_num_threads")
70 |
71 | return __set_num_threads(c_num_threads)
72 |
73 |
74 | cdef int __warn_and_fallback_on_default_domain(domain):
75 | warnings.warn(
76 | f"domain={domain} is expected to be an integer, a string ('blas', "
77 | "'fft', 'vml', 'pardiso', 'all'). Uing domain='all' instead."
78 | )
79 | return mkl.MKL_DOMAIN_ALL
80 |
81 |
82 | cdef int __domain_to_mkl_domain(domain):
83 | cdef int c_mkl_domain = mkl.MKL_DOMAIN_ALL
84 | _mapping = {
85 | "blas": mkl.MKL_DOMAIN_BLAS,
86 | "fft": mkl.MKL_DOMAIN_FFT,
87 | "vml": mkl.MKL_DOMAIN_VML,
88 | "pardiso": mkl.MKL_DOMAIN_PARDISO,
89 | "all": mkl.MKL_DOMAIN_ALL
90 | }
91 |
92 | if isinstance(domain, numbers.Integral):
93 | c_mkl_domain = domain
94 | elif isinstance(domain, str):
95 | if domain not in _mapping:
96 | c_mkl_domain = __warn_and_fallback_on_default_domain(domain)
97 | else:
98 | c_mkl_domain = _mapping[domain]
99 | else:
100 | c_mkl_domain = __warn_and_fallback_on_default_domain(domain)
101 |
102 | return c_mkl_domain
103 |
104 |
105 | cpdef domain_set_num_threads(num_threads, domain="all"):
106 | """
107 | Specifies the number of OpenMP* threads for a particular function domain.
108 | """
109 | cdef c_num_threads = __python_obj_to_int(num_threads, "domain_set_num_threads")
110 | __check_non_negative_num_threads(c_num_threads, "domain_set_num_threads")
111 |
112 | cdef int c_mkl_domain = __domain_to_mkl_domain(domain)
113 | cdef int c_mkl_status = __domain_set_num_threads(c_num_threads, c_mkl_domain)
114 |
115 | return __mkl_status_to_string(c_mkl_status)
116 |
117 |
118 | cpdef set_num_threads_local(num_threads):
119 | """
120 | Specifies the number of OpenMP* threads for all Intel(R) MKL functions on the
121 | current execution thread.
122 | """
123 | cdef c_num_threads = 0
124 | if isinstance(num_threads, str):
125 | if num_threads is not "global_num_threads":
126 | raise ValueError(
127 | "The argument of set_num_threads_local is expected "
128 | "to be a non-negative integer or a string 'global_num_threads'"
129 | )
130 | else:
131 | c_num_threads = __python_obj_to_int(num_threads, "set_num_threads_local")
132 |
133 | __check_non_negative_num_threads(c_num_threads, "set_num_threads_local")
134 |
135 | cdef c_prev_num_threads = __set_num_threads_local(c_num_threads)
136 | if (c_prev_num_threads == 0):
137 | ret_value = "global_num_threads"
138 | else:
139 | ret_value = c_prev_num_threads
140 |
141 | return ret_value
142 |
143 |
144 | cpdef set_dynamic(enable):
145 | """
146 | Enables Intel(R) MKL to dynamically change the number of OpenMP* threads.
147 | """
148 | cdef int c_enable = int(enable)
149 | # return the number of threads used
150 | return __set_dynamic(c_enable)
151 |
152 |
153 | cpdef get_max_threads():
154 | """
155 | Gets the number of OpenMP* threads targeted for parallelism.
156 | """
157 | return __get_max_threads()
158 |
159 |
160 | cpdef domain_get_max_threads(domain="all"):
161 | """
162 | Gets the number of OpenMP* threads targeted for parallelism for a particular
163 | function domain.
164 | """
165 | cdef int c_mkl_domain = __domain_to_mkl_domain(domain)
166 | return __domain_get_max_threads(c_mkl_domain)
167 |
168 |
169 | cpdef get_dynamic():
170 | """
171 | Determines whether Intel(R) MKL is enabled to dynamically change the number
172 | of OpenMP* threads.
173 | """
174 | return bool(__get_dynamic())
175 |
176 |
177 | cpdef int set_num_stripes(int num_stripes):
178 | """
179 | Specifies the number of stripes, or partitions along the leading dimension
180 | of the output matrix, for the parallel ``?gemm`` functions.
181 |
182 | Setting `num_stripes` argument to zero instructs Intel(R) MKL to default
183 | partitioning algorithm. A positive `num_stripes` arguments specifies a hint,
184 | and the library may actually use a smaller numbers.
185 |
186 | Returns the number of stripes the library uses, or a zero.
187 | """
188 | if num_stripes < 0:
189 | raise ValueError(
190 | "Expected non-negative number of stripes"
191 | ", got {}".format(num_stripes)
192 | )
193 | mkl.mkl_set_num_stripes(num_stripes)
194 | return mkl.mkl_get_num_stripes()
195 |
196 |
197 | cpdef int get_num_stripes():
198 | """
199 | Returns the number of stripes, or partitions along the leading dimension
200 | of the output matrix, for the parallel ``?gemm`` functions.
201 |
202 | Non-positive returned value indicates Intel(R) MKL uses default partitioning
203 | algorithm.
204 |
205 | Positive returned value is a hint, and the library may actually use a
206 | smaller number.
207 | """
208 | return mkl.mkl_get_num_stripes()
209 |
210 |
211 | # Timing
212 | cpdef second():
213 | """
214 | Returns elapsed time in seconds.
215 | Use to estimate real time between two calls to this function.
216 | https://www.intel.com/content/www/us/en/developer/overview.html
217 | """
218 | return __second()
219 |
220 |
221 | cpdef dsecnd():
222 | """
223 | Returns elapsed time in seconds.
224 | Use to estimate real time between two calls to this function.
225 | https://www.intel.com/content/www/us/en/developer/overview.html
226 | """
227 | return __dsecnd()
228 |
229 |
230 | cpdef get_cpu_clocks():
231 | """
232 | Returns elapsed CPU clocks.
233 | https://www.intel.com/content/www/us/en/developer/overview.html
234 | """
235 | return __get_cpu_clocks()
236 |
237 |
238 | cpdef get_cpu_frequency():
239 | """
240 | Returns the current CPU frequency value in GHz.
241 | https://www.intel.com/content/www/us/en/developer/overview.html
242 | """
243 | return __get_cpu_frequency()
244 |
245 |
246 | cpdef get_max_cpu_frequency():
247 | """
248 | Returns the maximum CPU frequency value in GHz.
249 | """
250 | return __get_max_cpu_frequency()
251 |
252 |
253 | cpdef get_clocks_frequency():
254 | """
255 | Returns the frequency value in GHz based on constant-rate Time Stamp Counter.
256 |
257 | """
258 | return __get_clocks_frequency()
259 |
260 |
261 | # Memory Management. See the Intel(R) MKL Developer Guide for more memory usage
262 | # information.
263 | cpdef free_buffers():
264 | """
265 | Frees unused memory allocated by the Intel(R) MKL Memory Allocator.
266 | """
267 | __free_buffers()
268 |
269 |
270 | cpdef thread_free_buffers():
271 | """
272 | Frees unused memory allocated by the Intel(R) MKL Memory Allocator in the current
273 | thread.
274 | """
275 | __thread_free_buffers()
276 |
277 |
278 | cpdef disable_fast_mm():
279 | """
280 | Turns off the Intel(R) MKL Memory Allocator for Intel(R) MKL functions to directly
281 | use the system malloc/free functions.
282 | """
283 | return __disable_fast_mm()
284 |
285 |
286 | cpdef mem_stat():
287 | """
288 | Reports the status of the Intel(R) MKL Memory Allocator.
289 | """
290 | return __mem_stat()
291 |
292 |
293 | cpdef peak_mem_usage(mem_const):
294 | """
295 | Reports the peak memory allocated by the Intel(R) MKL Memory Allocator.
296 | """
297 | return __peak_mem_usage(mem_const)
298 |
299 |
300 | cpdef set_memory_limit(limit):
301 | """
302 | On Linux, sets the limit of memory that Intel(R) MKL can allocate for a specified
303 | type of memory.
304 | """
305 | return __set_memory_limit(limit)
306 |
307 |
308 | # Conditional Numerical Reproducibility
309 | cpdef cbwr_set(branch=None):
310 | """
311 | Configures the CNR mode of Intel(R) MKL.
312 | """
313 | return __cbwr_set(branch)
314 |
315 |
316 | cpdef cbwr_get(cnr_const="all"):
317 | """
318 | Returns the current CNR settings.
319 | """
320 | return __cbwr_get(cnr_const)
321 |
322 |
323 | cpdef cbwr_get_auto_branch():
324 | """
325 | Automatically detects the CNR code branch for your platform.
326 | """
327 | return __cbwr_get_auto_branch()
328 |
329 |
330 | # Miscellaneous
331 | cpdef enable_instructions(isa=None):
332 | """
333 | Enables dispatching for new Intel architectures or restricts the set of Intel
334 | instruction sets available for dispatching.
335 | """
336 | return __enable_instructions(isa)
337 |
338 |
339 | cpdef set_env_mode():
340 | """
341 | Sets up the mode that ignores environment settings specific to Intel(R) MKL.
342 | See mkl_set_env_mode(1).
343 | """
344 | return __set_env_mode()
345 |
346 |
347 | cpdef get_env_mode():
348 | """
349 | Query the current environment mode. See mkl_set_env_mode(0).
350 | """
351 | return __get_env_mode()
352 |
353 |
354 | cpdef verbose(enable):
355 | """
356 | Enables or disables Intel(R) MKL Verbose mode.
357 | """
358 | cdef int c_enable = int(enable)
359 | return bool(__verbose(c_enable))
360 |
361 |
362 | cpdef set_mpi(vendor, custom_library_name=None):
363 | """
364 | Sets the implementation of the message-passing interface to be used by Intel(R) MKL.
365 | """
366 | return __set_mpi(vendor, custom_library_name)
367 |
368 |
369 | # VM Service Functions
370 | cpdef vml_set_mode(accuracy, ftzdaz, errmode):
371 | """
372 | Sets a new mode for VM functions according to the mode parameter and stores the
373 | previous VM mode to oldmode.
374 | """
375 | return __vml_set_mode(accuracy, ftzdaz, errmode)
376 |
377 |
378 | cpdef vml_get_mode():
379 | """
380 | Gets the VM mode.
381 | """
382 | return __vml_get_mode()
383 |
384 |
385 | cpdef vml_set_err_status(status):
386 | """
387 | Sets the new VM Error Status according to err and stores the previous VM Error
388 | Status to olderr.
389 | """
390 | return __vml_set_err_status(status)
391 |
392 |
393 | cpdef vml_get_err_status():
394 | """
395 | Gets the VM Error Status.
396 | """
397 | return __vml_get_err_status()
398 |
399 |
400 | cpdef vml_clear_err_status():
401 | """
402 | Sets the VM Error Status to VML_STATUS_OK and stores the previous VM Error Status
403 | to olderr.
404 | """
405 | return __vml_clear_err_status()
406 |
407 |
408 | cdef str __mkl_status_to_string(int mkl_status) noexcept:
409 | if mkl_status == 1:
410 | return "success"
411 | else:
412 | return "error"
413 |
414 |
415 | cdef int __python_obj_to_int(obj, func_name) except *:
416 | if not isinstance(obj, numbers.Integral):
417 | raise ValueError(
418 | "The argument of " + func_name + " is expected to be a positive "
419 | "integer"
420 | )
421 | cdef int c_int = obj
422 | return c_int
423 |
424 |
425 | cdef void __check_positive_num_threads(int p, func_name) except *:
426 | if p <= 0:
427 | warnings.warn("Non-positive argument of " + func_name +
428 | " is being ignored, number of threads will not be changed")
429 |
430 |
431 | cdef void __check_non_negative_num_threads(int p, func_name) except *:
432 | if p < 0:
433 | warnings.warn("Negative argument of " + func_name +
434 | " is being ignored, number of threads will not be changed")
435 |
436 |
437 | cdef inline int __mkl_str_to_int(variable, possible_variables_dict) except *:
438 | if variable is None:
439 | raise ValueError("Variable can not be None")
440 | if possible_variables_dict is None:
441 | raise RuntimeError(
442 | "Dictionary mapping possible variable value to internal code is "
443 | "missing"
444 | )
445 | if variable not in possible_variables_dict:
446 | raise ValueError("Variable: <" + str(variable) + "> not in " +
447 | str(possible_variables_dict.keys()))
448 |
449 | return possible_variables_dict[variable]
450 |
451 |
452 | cdef __mkl_int_to_str(int mkl_int_variable, possible_variables_dict) except *:
453 | if possible_variables_dict is None:
454 | raise RuntimeError(
455 | "Dictionary mapping possible internal code to output string is "
456 | "missing"
457 | )
458 |
459 | if mkl_int_variable not in possible_variables_dict:
460 | raise ValueError("Variable: <" + str(mkl_int_variable) + "> not in " +
461 | str(possible_variables_dict.keys()))
462 |
463 | return possible_variables_dict[mkl_int_variable]
464 |
465 |
466 | # Version Information
467 | cdef mkl.MKLVersion __get_version() noexcept:
468 | """
469 | Returns the Intel(R) MKL version.
470 | """
471 | cdef mkl.MKLVersion c_mkl_version
472 | mkl.mkl_get_version(&c_mkl_version)
473 | return c_mkl_version
474 |
475 |
476 | cdef str __get_version_string() except *:
477 | """
478 | Returns the Intel(R) MKL version in a character string.
479 | """
480 | cdef int c_string_len = 198
481 | cdef char[198] c_string
482 | mkl.mkl_get_version_string(c_string, c_string_len)
483 | return c_string.decode()
484 |
485 |
486 | # Threading
487 | cdef inline int __set_num_threads(int num_threads) noexcept:
488 | """
489 | Specifies the number of OpenMP* threads to use.
490 | """
491 |
492 | cdef int prev_num_threads = __get_max_threads()
493 | mkl.mkl_set_num_threads(num_threads)
494 | return prev_num_threads
495 |
496 |
497 | cdef inline int __domain_set_num_threads(int c_num_threads, int mkl_domain) noexcept:
498 | """
499 | Specifies the number of OpenMP* threads for a particular function domain.
500 | """
501 | cdef int mkl_status = mkl.mkl_domain_set_num_threads(c_num_threads, mkl_domain)
502 | return mkl_status
503 |
504 |
505 | cdef inline int __set_num_threads_local(int c_num_threads) noexcept:
506 | """
507 | Specifies the number of OpenMP* threads for all Intel(R) MKL functions on the
508 | current execution thread.
509 | """
510 |
511 | cdef int c_mkl_status = mkl.mkl_set_num_threads_local(c_num_threads)
512 | return c_mkl_status
513 |
514 |
515 | cdef inline int __set_dynamic(int c_enable) noexcept:
516 | """
517 | Enables Intel(R) MKL to dynamically change the number of OpenMP* threads.
518 | """
519 |
520 | mkl.mkl_set_dynamic(c_enable)
521 | return __get_max_threads()
522 |
523 |
524 | cdef inline int __get_max_threads() noexcept:
525 | """
526 | Gets the number of OpenMP* threads targeted for parallelism.
527 | """
528 | return mkl.mkl_get_max_threads()
529 |
530 |
531 | cdef inline int __domain_get_max_threads(int c_mkl_domain) noexcept:
532 | """
533 | Gets the number of OpenMP* threads targeted for parallelism for a particular
534 | function domain.
535 | """
536 | cdef int c_num_threads = mkl.mkl_domain_get_max_threads(c_mkl_domain)
537 |
538 | return c_num_threads
539 |
540 |
541 | cdef inline int __get_dynamic() noexcept:
542 | """
543 | Determines whether Intel(R) MKL is enabled to dynamically change the number of
544 | OpenMP* threads.
545 | """
546 | return mkl.mkl_get_dynamic()
547 |
548 |
549 | # Timing
550 | cdef inline float __second() noexcept:
551 | """
552 | Returns elapsed time in seconds.
553 | Use to estimate real time between two calls to this function.
554 | https://www.intel.com/content/www/us/en/developer/overview.html
555 | """
556 | return mkl.second()
557 |
558 |
559 | cdef inline double __dsecnd() noexcept:
560 | """
561 | Returns elapsed time in seconds.
562 | Use to estimate real time between two calls to this function.
563 | https://www.intel.com/content/www/us/en/developer/overview.html
564 | """
565 | return mkl.dsecnd()
566 |
567 |
568 | cdef inline mkl.MKL_UINT64 __get_cpu_clocks() noexcept:
569 | """
570 | Returns elapsed CPU clocks.
571 | """
572 | cdef mkl.MKL_UINT64 clocks
573 | mkl.mkl_get_cpu_clocks(&clocks)
574 | return clocks
575 |
576 |
577 | cdef inline double __get_cpu_frequency() noexcept:
578 | """
579 | Returns the current CPU frequency value in GHz.
580 | """
581 | return mkl.mkl_get_cpu_frequency()
582 |
583 |
584 | cdef inline double __get_max_cpu_frequency() noexcept:
585 | """
586 | Returns the maximum CPU frequency value in GHz.
587 | """
588 | return mkl.mkl_get_max_cpu_frequency()
589 |
590 |
591 | cdef inline double __get_clocks_frequency() noexcept:
592 | """
593 | Returns the frequency value in GHz based on constant-rate Time Stamp Counter.
594 | """
595 | return mkl.mkl_get_clocks_frequency()
596 |
597 |
598 | # Memory Management. See the Intel(R) MKL Developer Guide for more memory usage
599 | # information.
600 | cdef inline void __free_buffers() noexcept:
601 | """
602 | Frees unused memory allocated by the Intel(R) MKL Memory Allocator.
603 | """
604 | mkl.mkl_free_buffers()
605 | return
606 |
607 |
608 | cdef inline void __thread_free_buffers() noexcept:
609 | """
610 | Frees unused memory allocated by the Intel(R) MKL Memory Allocator in the current
611 | thread.
612 | """
613 | mkl.mkl_thread_free_buffers()
614 | return
615 |
616 |
617 | cdef inline int __disable_fast_mm() noexcept:
618 | """
619 | Turns off the Intel(R) MKL Memory Allocator for Intel(R) MKL functions to directly
620 | use the system malloc/free functions.
621 | """
622 | return mkl.mkl_disable_fast_mm()
623 |
624 |
625 | cdef inline MemStatData __mem_stat() noexcept:
626 | """
627 | Reports the status of the Intel(R) MKL Memory Allocator.
628 | """
629 | cdef MemStatData mem_stat_data
630 | mem_stat_data.allocated_bytes = mkl.mkl_mem_stat(&mem_stat_data.allocated_buffers)
631 | return mem_stat_data
632 |
633 |
634 | cdef object __peak_mem_usage(mem_const) except *:
635 | """
636 | Reports the peak memory allocated by the Intel(R) MKL Memory Allocator.
637 | """
638 | __variables = {
639 | "input": {
640 | "enable": mkl.MKL_PEAK_MEM_ENABLE,
641 | "disable": mkl.MKL_PEAK_MEM_DISABLE,
642 | "peak_mem": mkl.MKL_PEAK_MEM,
643 | "peak_mem_reset": mkl.MKL_PEAK_MEM_RESET,
644 | }
645 | }
646 | cdef int c_mkl_mem_const = __mkl_str_to_int(mem_const, __variables["input"])
647 |
648 | cdef mkl.MKL_INT64 c_memory_allocator = mkl.mkl_peak_mem_usage(c_mkl_mem_const)
649 |
650 | if c_memory_allocator == -1:
651 | memory_allocator = "error"
652 | else:
653 | memory_allocator = c_memory_allocator
654 | return memory_allocator
655 |
656 |
657 | cdef inline object __set_memory_limit(limit) except *:
658 | """
659 | On Linux, sets the limit of memory that Intel(R) MKL can allocate for a specified
660 | type of memory.
661 | """
662 | cdef size_t c_limit = limit
663 |
664 | cdef int c_mkl_status = mkl.mkl_set_memory_limit(mkl.MKL_MEM_MCDRAM, c_limit)
665 | return __mkl_status_to_string(c_mkl_status)
666 |
667 |
668 | # Conditional Numerical Reproducibility
669 | cdef object __cbwr_set(branch=None) except *:
670 | """
671 | Configures the CNR mode of Intel(R) MKL.
672 | """
673 | __variables = {
674 | "input": {
675 | "off": mkl.MKL_CBWR_OFF,
676 | "branch_off": mkl.MKL_CBWR_BRANCH_OFF,
677 | "auto": mkl.MKL_CBWR_AUTO,
678 | "compatible": mkl.MKL_CBWR_COMPATIBLE,
679 | "sse2": mkl.MKL_CBWR_SSE2,
680 | "ssse3": mkl.MKL_CBWR_SSSE3,
681 | "sse4_1": mkl.MKL_CBWR_SSE4_1,
682 | "sse4_2": mkl.MKL_CBWR_SSE4_2,
683 | "avx": mkl.MKL_CBWR_AVX,
684 | "avx2": mkl.MKL_CBWR_AVX2,
685 | "avx2,strict": mkl.MKL_CBWR_AVX2 | mkl.MKL_CBWR_STRICT,
686 | "avx512_mic": mkl.MKL_CBWR_AVX512_MIC,
687 | "avx512_mic,strict": mkl.MKL_CBWR_AVX512_MIC | mkl.MKL_CBWR_STRICT,
688 | "avx512": mkl.MKL_CBWR_AVX512,
689 | "avx512,strict": mkl.MKL_CBWR_AVX512 | mkl.MKL_CBWR_STRICT,
690 | "avx512_mic_e1": mkl.MKL_CBWR_AVX512_MIC_E1,
691 | "avx512_e1": mkl.MKL_CBWR_AVX512_E1,
692 | "avx512_e1,strict": mkl.MKL_CBWR_AVX512_E1 | mkl.MKL_CBWR_STRICT,
693 | },
694 | "output": {
695 | mkl.MKL_CBWR_SUCCESS: "success",
696 | mkl.MKL_CBWR_ERR_INVALID_INPUT: "err_invalid_input",
697 | mkl.MKL_CBWR_ERR_UNSUPPORTED_BRANCH: "err_unsupported_branch",
698 | mkl.MKL_CBWR_ERR_MODE_CHANGE_FAILURE: "err_mode_change_failure",
699 | },
700 | }
701 | mkl_branch = __mkl_str_to_int(branch, __variables["input"])
702 |
703 | mkl_status = mkl.mkl_cbwr_set(mkl_branch)
704 |
705 | status = __mkl_int_to_str(mkl_status, __variables["output"])
706 | return status
707 |
708 |
709 | cdef inline __cbwr_get(cnr_const=None) except *:
710 | """
711 | Returns the current CNR settings.
712 | """
713 | __variables = {
714 | "input": {
715 | "branch": mkl.MKL_CBWR_BRANCH,
716 | "all": mkl.MKL_CBWR_ALL,
717 | },
718 | "output": {
719 | mkl.MKL_CBWR_BRANCH_OFF: "branch_off",
720 | mkl.MKL_CBWR_AUTO: "auto",
721 | mkl.MKL_CBWR_COMPATIBLE: "compatible",
722 | mkl.MKL_CBWR_SSE2: "sse2",
723 | mkl.MKL_CBWR_SSSE3: "ssse3",
724 | mkl.MKL_CBWR_SSE4_1: "sse4_1",
725 | mkl.MKL_CBWR_SSE4_2: "sse4_2",
726 | mkl.MKL_CBWR_AVX: "avx",
727 | mkl.MKL_CBWR_AVX2: "avx2",
728 | mkl.MKL_CBWR_AVX2 | mkl.MKL_CBWR_STRICT: "avx2,strict",
729 | mkl.MKL_CBWR_AVX512_MIC: "avx512_mic",
730 | mkl.MKL_CBWR_AVX512_MIC | mkl.MKL_CBWR_STRICT: "avx512_mic,strict",
731 | mkl.MKL_CBWR_AVX512: "avx512",
732 | mkl.MKL_CBWR_AVX512 | mkl.MKL_CBWR_STRICT: "avx512,strict",
733 | mkl.MKL_CBWR_AVX512_MIC_E1: "avx512_mic_e1",
734 | mkl.MKL_CBWR_AVX512_E1: "avx512_e1",
735 | mkl.MKL_CBWR_AVX512_E1 | mkl.MKL_CBWR_STRICT: "avx512_e1,strict",
736 | mkl.MKL_CBWR_ERR_INVALID_INPUT: "err_invalid_input",
737 | },
738 | }
739 | mkl_cnr_const = __mkl_str_to_int(cnr_const, __variables["input"])
740 |
741 | mkl_status = mkl.mkl_cbwr_get(mkl_cnr_const)
742 |
743 | status = __mkl_int_to_str(mkl_status, __variables["output"])
744 | return status
745 |
746 |
747 | cdef object __cbwr_get_auto_branch() except *:
748 | """
749 | Automatically detects the CNR code branch for your platform.
750 | """
751 | __variables = {
752 | "output": {
753 | mkl.MKL_CBWR_BRANCH_OFF: "branch_off",
754 | mkl.MKL_CBWR_AUTO: "auto",
755 | mkl.MKL_CBWR_COMPATIBLE: "compatible",
756 | mkl.MKL_CBWR_SSE2: "sse2",
757 | mkl.MKL_CBWR_SSSE3: "ssse3",
758 | mkl.MKL_CBWR_SSE4_1: "sse4_1",
759 | mkl.MKL_CBWR_SSE4_2: "sse4_2",
760 | mkl.MKL_CBWR_AVX: "avx",
761 | mkl.MKL_CBWR_AVX2: "avx2",
762 | mkl.MKL_CBWR_AVX2 | mkl.MKL_CBWR_STRICT: "avx2,strict",
763 | mkl.MKL_CBWR_AVX512_MIC: "avx512_mic",
764 | mkl.MKL_CBWR_AVX512_MIC | mkl.MKL_CBWR_STRICT: "avx512_mic,strict",
765 | mkl.MKL_CBWR_AVX512: "avx512",
766 | mkl.MKL_CBWR_AVX512 | mkl.MKL_CBWR_STRICT: "avx512,strict",
767 | mkl.MKL_CBWR_AVX512_MIC_E1: "avx512_mic_e1",
768 | mkl.MKL_CBWR_AVX512_E1: "avx512_e1",
769 | mkl.MKL_CBWR_AVX512_E1 | mkl.MKL_CBWR_STRICT: "avx512_e1,strict",
770 | mkl.MKL_CBWR_SUCCESS: "success",
771 | mkl.MKL_CBWR_ERR_INVALID_INPUT: "err_invalid_input",
772 | },
773 | }
774 |
775 | mkl_status = mkl.mkl_cbwr_get_auto_branch()
776 |
777 | status = __mkl_int_to_str(mkl_status, __variables["output"])
778 | return status
779 |
780 |
781 | # Miscellaneous
782 | cdef object __enable_instructions(isa=None) except *:
783 | """
784 | Enables dispatching for new Intel architectures or restricts the set of Intel
785 | instruction sets available for dispatching.
786 | """
787 | __variables = {
788 | "input": {
789 | "single_path": mkl.MKL_SINGLE_PATH_ENABLE,
790 | "avx512_e4": mkl.MKL_ENABLE_AVX512_E4,
791 | "avx512_e3": mkl.MKL_ENABLE_AVX512_E3,
792 | "avx512_e2": mkl.MKL_ENABLE_AVX512_E2,
793 | "avx512_e1": mkl.MKL_ENABLE_AVX512_E1,
794 | "avx512_mic_e1": mkl.MKL_ENABLE_AVX512_MIC_E1,
795 | "avx512": mkl.MKL_ENABLE_AVX512,
796 | "avx512_mic": mkl.MKL_ENABLE_AVX512_MIC,
797 | "avx2_e1": mkl.MKL_ENABLE_AVX2_E1,
798 | "avx2": mkl.MKL_ENABLE_AVX2,
799 | "avx": mkl.MKL_ENABLE_AVX,
800 | "sse4_2": mkl.MKL_ENABLE_SSE4_2,
801 | },
802 | }
803 | cdef int c_mkl_isa = __mkl_str_to_int(isa, __variables["input"])
804 |
805 | cdef int c_mkl_status = mkl.mkl_enable_instructions(c_mkl_isa)
806 |
807 | return __mkl_status_to_string(c_mkl_status)
808 |
809 |
810 | cdef object __set_env_mode() except *:
811 | """
812 | Sets up the mode that ignores environment settings specific to Intel(R) MKL.
813 | See mkl_set_env_mode(1).
814 | """
815 | __variables = {
816 | "input": None,
817 | "output": {
818 | 0: "default",
819 | 1: "ignore",
820 | },
821 | }
822 | cdef int c_mkl_status = mkl.mkl_set_env_mode(1)
823 |
824 | status = __mkl_int_to_str(c_mkl_status, __variables["output"])
825 | return status
826 |
827 |
828 | cdef object __get_env_mode() except *:
829 | """
830 | Query the current environment mode. See mkl_set_env_mode(0).
831 | """
832 | __variables = {
833 | "output": {
834 | 0: "default",
835 | 1: "ignore",
836 | },
837 | }
838 | cdef int c_mkl_status = mkl.mkl_set_env_mode(0)
839 |
840 | status = __mkl_int_to_str(c_mkl_status, __variables["output"])
841 | return status
842 |
843 |
844 | cdef inline int __verbose(int c_enable) noexcept:
845 | """
846 | Enables or disables Intel(R) MKL Verbose mode.
847 | """
848 | return mkl.mkl_verbose(c_enable)
849 |
850 |
851 | cdef __set_mpi(vendor, custom_library_name=None) except *:
852 | """
853 | Sets the implementation of the message-passing interface to be used by Intel(R) MKL.
854 | """
855 | __variables = {
856 | "input": {
857 | "custom": mkl.MKL_BLACS_CUSTOM,
858 | "msmpi": mkl.MKL_BLACS_MSMPI,
859 | "intelmpi": mkl.MKL_BLACS_INTELMPI,
860 | },
861 | "output": {
862 | 0: "success",
863 | -1: "vendor_invalid",
864 | -2: "custom_library_name_invalid",
865 | -3: "MPI library cannot be set at this point",
866 | },
867 | }
868 | if mkl.MKL_BLACS_LASTMPI > mkl.MKL_BLACS_INTELMPI + 1:
869 | __variables["input"]["mpich2"] = mkl.MKL_BLACS_MPICH2
870 | if (
871 | (vendor is "custom" or custom_library_name is not None)
872 | and (vendor is not "custom" or custom_library_name is None)
873 | ):
874 | raise ValueError("Selecting custom MPI for BLACS requires specifying "
875 | "the custom library, and specifying custom library "
876 | "necessitates selecting a custom MPI for BLACS library")
877 | mkl_vendor = __mkl_str_to_int(vendor, __variables["input"])
878 |
879 | cdef bytes c_bytes
880 | cdef char* c_string = ""
881 | if custom_library_name is not None:
882 | c_bytes = custom_library_name.encode()
883 | c_string = c_bytes
884 | mkl_status = mkl.mkl_set_mpi(mkl_vendor, c_string)
885 |
886 | status = __mkl_int_to_str(mkl_status, __variables["output"])
887 | return status
888 |
889 |
890 | # VM Service Functions
891 | cdef object __vml_set_mode(accuracy, ftzdaz, errmode) except *:
892 | """
893 | Sets a new mode for VM functions according to the mode parameter and stores the
894 | previous VM mode to oldmode.
895 | """
896 | __variables = {
897 | "input": {
898 | "accuracy": {
899 | "ha": mkl.VML_HA,
900 | "la": mkl.VML_LA,
901 | "ep": mkl.VML_EP,
902 | },
903 | "ftzdaz": {
904 | "on": mkl.VML_FTZDAZ_ON,
905 | "off": mkl.VML_FTZDAZ_OFF,
906 | "default": 0,
907 | },
908 | "errmode": {
909 | "ignore": mkl.VML_ERRMODE_IGNORE,
910 | "errno": mkl.VML_ERRMODE_ERRNO,
911 | "stderr": mkl.VML_ERRMODE_STDERR,
912 | "except": mkl.VML_ERRMODE_EXCEPT,
913 | "callback": mkl.VML_ERRMODE_CALLBACK,
914 | "default": mkl.VML_ERRMODE_DEFAULT,
915 | },
916 | },
917 | "output": {
918 | "accuracy": {
919 | mkl.VML_HA: "ha",
920 | mkl.VML_LA: "la",
921 | mkl.VML_EP: "ep",
922 | },
923 | "ftzdaz": {
924 | mkl.VML_FTZDAZ_ON: "on",
925 | mkl.VML_FTZDAZ_OFF: "off",
926 | 0: "default",
927 | },
928 | "errmode": {
929 | mkl.VML_ERRMODE_IGNORE: "ignore",
930 | mkl.VML_ERRMODE_ERRNO: "errno",
931 | mkl.VML_ERRMODE_STDERR: "stderr",
932 | mkl.VML_ERRMODE_EXCEPT: "except",
933 | mkl.VML_ERRMODE_CALLBACK: "callback",
934 | mkl.VML_ERRMODE_DEFAULT: "default",
935 | },
936 | },
937 | }
938 | cdef int c_mkl_accuracy = __mkl_str_to_int(
939 | accuracy, __variables["input"]["accuracy"]
940 | )
941 | cdef int c_mkl_ftzdaz = __mkl_str_to_int(ftzdaz, __variables["input"]["ftzdaz"])
942 | cdef int c_mkl_errmode = __mkl_str_to_int(errmode, __variables["input"]["errmode"])
943 |
944 | cdef int c_mkl_status = mkl.vmlSetMode(
945 | c_mkl_accuracy | c_mkl_ftzdaz | c_mkl_errmode
946 | )
947 |
948 | accuracy = __mkl_int_to_str(
949 | c_mkl_status & mkl.VML_ACCURACY_MASK,
950 | __variables["output"]["accuracy"])
951 | ftzdaz = __mkl_int_to_str(
952 | c_mkl_status & mkl.VML_FTZDAZ_MASK,
953 | __variables["output"]["ftzdaz"])
954 | errmode = __mkl_int_to_str(
955 | c_mkl_status & mkl.VML_ERRMODE_MASK,
956 | __variables["output"]["errmode"])
957 |
958 | return (accuracy, ftzdaz, errmode)
959 |
960 |
961 | cdef object __vml_get_mode() except *:
962 | """
963 | Gets the VM mode.
964 | """
965 | __variables = {
966 | "output": {
967 | "accuracy": {
968 | mkl.VML_HA: "ha",
969 | mkl.VML_LA: "la",
970 | mkl.VML_EP: "ep",
971 | },
972 | "ftzdaz": {
973 | mkl.VML_FTZDAZ_ON: "on",
974 | mkl.VML_FTZDAZ_OFF: "off",
975 | 0: "default",
976 | },
977 | "errmode": {
978 | mkl.VML_ERRMODE_IGNORE: "ignore",
979 | mkl.VML_ERRMODE_ERRNO: "errno",
980 | mkl.VML_ERRMODE_STDERR: "stderr",
981 | mkl.VML_ERRMODE_EXCEPT: "except",
982 | mkl.VML_ERRMODE_CALLBACK: "callback",
983 | mkl.VML_ERRMODE_DEFAULT: "default",
984 | },
985 | },
986 | }
987 |
988 | cdef int c_mkl_status = mkl.vmlGetMode()
989 |
990 | accuracy = __mkl_int_to_str(
991 | c_mkl_status & mkl.VML_ACCURACY_MASK,
992 | __variables["output"]["accuracy"])
993 | ftzdaz = __mkl_int_to_str(
994 | c_mkl_status & mkl.VML_FTZDAZ_MASK,
995 | __variables["output"]["ftzdaz"])
996 | errmode = __mkl_int_to_str(
997 | c_mkl_status & mkl.VML_ERRMODE_MASK,
998 | __variables["output"]["errmode"])
999 | return (accuracy, ftzdaz, errmode)
1000 |
1001 |
1002 | __mkl_vml_status = {
1003 | "ok": mkl.VML_STATUS_OK,
1004 | "accuracywarning": mkl.VML_STATUS_ACCURACYWARNING,
1005 | "badsize": mkl.VML_STATUS_BADSIZE,
1006 | "badmem": mkl.VML_STATUS_BADMEM,
1007 | "errdom": mkl.VML_STATUS_ERRDOM,
1008 | "sing": mkl.VML_STATUS_SING,
1009 | "overflow": mkl.VML_STATUS_OVERFLOW,
1010 | "underflow": mkl.VML_STATUS_UNDERFLOW,
1011 | }
1012 |
1013 |
1014 | cdef object __vml_set_err_status(status) except *:
1015 | """
1016 | Sets the new VM Error Status according to err and stores the previous VM Error
1017 | Status to olderr.
1018 | """
1019 | __variables = {
1020 | "input": {
1021 | "ok": mkl.VML_STATUS_OK,
1022 | "accuracywarning": mkl.VML_STATUS_ACCURACYWARNING,
1023 | "badsize": mkl.VML_STATUS_BADSIZE,
1024 | "badmem": mkl.VML_STATUS_BADMEM,
1025 | "errdom": mkl.VML_STATUS_ERRDOM,
1026 | "sing": mkl.VML_STATUS_SING,
1027 | "overflow": mkl.VML_STATUS_OVERFLOW,
1028 | "underflow": mkl.VML_STATUS_UNDERFLOW,
1029 | },
1030 | "output": {
1031 | mkl.VML_STATUS_OK: "ok",
1032 | mkl.VML_STATUS_ACCURACYWARNING: "accuracywarning",
1033 | mkl.VML_STATUS_BADSIZE: "badsize",
1034 | mkl.VML_STATUS_BADMEM: "badmem",
1035 | mkl.VML_STATUS_ERRDOM: "errdom",
1036 | mkl.VML_STATUS_SING: "sing",
1037 | mkl.VML_STATUS_OVERFLOW: "overflow",
1038 | mkl.VML_STATUS_UNDERFLOW: "underflow",
1039 | },
1040 | }
1041 | cdef int mkl_status_in = __mkl_str_to_int(status, __variables["input"])
1042 |
1043 | cdef int mkl_status_out = mkl.vmlSetErrStatus(mkl_status_in)
1044 |
1045 | status = __mkl_int_to_str(mkl_status_out, __variables["output"])
1046 | return status
1047 |
1048 |
1049 | cdef object __vml_get_err_status() except *:
1050 | """
1051 | Gets the VM Error Status.
1052 | """
1053 | __variables = {
1054 | "input": None,
1055 | "output": {
1056 | mkl.VML_STATUS_OK: "ok",
1057 | mkl.VML_STATUS_ACCURACYWARNING: "accuracywarning",
1058 | mkl.VML_STATUS_BADSIZE: "badsize",
1059 | mkl.VML_STATUS_BADMEM: "badmem",
1060 | mkl.VML_STATUS_ERRDOM: "errdom",
1061 | mkl.VML_STATUS_SING: "sing",
1062 | mkl.VML_STATUS_OVERFLOW: "overflow",
1063 | mkl.VML_STATUS_UNDERFLOW: "underflow",
1064 | },
1065 | }
1066 |
1067 | cdef int mkl_status = mkl.vmlGetErrStatus()
1068 |
1069 | status = __mkl_int_to_str(mkl_status, __variables["output"])
1070 | return status
1071 |
1072 |
1073 | cdef object __vml_clear_err_status() except *:
1074 | """
1075 | Sets the VM Error Status to VML_STATUS_OK and stores the previous VM Error Status
1076 | to olderr.
1077 | """
1078 | __variables = {
1079 | "input": None,
1080 | "output": {
1081 | mkl.VML_STATUS_OK: "ok",
1082 | mkl.VML_STATUS_ACCURACYWARNING: "accuracywarning",
1083 | mkl.VML_STATUS_BADSIZE: "badsize",
1084 | mkl.VML_STATUS_BADMEM: "badmem",
1085 | mkl.VML_STATUS_ERRDOM: "errdom",
1086 | mkl.VML_STATUS_SING: "sing",
1087 | mkl.VML_STATUS_OVERFLOW: "overflow",
1088 | mkl.VML_STATUS_UNDERFLOW: "underflow",
1089 | },
1090 | }
1091 |
1092 | cdef int mkl_status = mkl.vmlClearErrStatus()
1093 |
1094 | status = __mkl_int_to_str(mkl_status, __variables["output"])
1095 | return status
1096 |
--------------------------------------------------------------------------------