From cbdc78534353939ec81c31a3138515860aac0b33 Mon Sep 17 00:00:00 2001 From: Ralf Gommers Date: Tue, 10 Oct 2023 00:27:02 +0200 Subject: [PATCH 1/6] ENH: meson: implement BLAS/LAPACK auto-detection and many CI jobs [wheel build] This reimplements the auto-detection and many of the switches that `numpy.distutils` offered. Beyond that, it implements several new features: - Auto-detect the symbol suffix for ILP64 OpenBLAS (can be none or `64_`) - MKL ILP64 support, threading control, and use of the layered library model for MKL >=2023.0 - FlexiBLAS support (LP64 and ILP64) - Support for the upcoming standard in Reference LAPACK for `_64` ILP64 symbol suffix convention. - A test suite for BLAS/LAPACK libraries, covering: - OpenBLAS: LP64, ILP64 detected via pkg-config and with a "system dependency" (i.e., custom code inside Meson) - MKL: LP64, ILP64 (layered) and LP64 (SDL) - Accelerate: LP64, ILP64 on macOS >=13.3 - FlexiBLAS: LP64, ILP64 on Fedora - ATLAS (LP64, via pkg-config only) - BLIS (LP64, via pkg-config only) - plain libblas/liblapack (Netlib, LP64 only) The list of libraries that is tried with the default 'auto' setting excludes a couple of libraries, because they're either no longer developed (ATLAS), not mature (libflame), or can't be tested and may be re-added later (ArmPL, ssl2). Those libraries can still be quite easily used via pkg-config. The new CI jobs are running by default right now. Once things settle down, the plan is to disable them by default and allow triggering them via a `[blas ci]` command in the commit message (just like for wheel builds). Docs will be included in a separate PR with the pending rewrite of all the build/install docs. For now, the CI jobs and the `meson_options.txt` file serve as guidance for how to use this. Note that the test suite contains a few hacks, because of packaging bugs for MKL on PyPI (broken .pc files) and BLIS (missing .pc file in Debian). --- .github/workflows/linux_meson.yml | 284 +++++++++++++++++++++++++++++- .github/workflows/linux_musl.yml | 14 +- .github/workflows/macos.yml | 19 +- azure-steps-windows.yml | 5 +- build_requirements.txt | 2 +- meson.build | 2 - meson_options.txt | 18 +- numpy/core/src/common/npy_cblas.h | 15 +- numpy/meson.build | 244 +++++++++++-------------- pyproject.toml | 12 +- tools/ci/_blis_debian.pc | 8 + vendored-meson/meson | 2 +- 12 files changed, 448 insertions(+), 177 deletions(-) create mode 100644 tools/ci/_blis_debian.pc diff --git a/.github/workflows/linux_meson.yml b/.github/workflows/linux_meson.yml index 7be5cb38bfc2..ebbd52997e42 100644 --- a/.github/workflows/linux_meson.yml +++ b/.github/workflows/linux_meson.yml @@ -1,4 +1,36 @@ -name: Test Meson build (Linux) +name: BLAS tests (Linux) + +# This file is meant for testing different BLAS/LAPACK flavors and build +# options on Linux. All other yml files for Linux will only test without BLAS +# (mostly because that's easier and faster to build) or with the same 64-bit +# OpenBLAS build that is used in the wheel jobs. +# +# Jobs and their purpose: +# +# - openblas32_stable_nightly: +# Uses the 32-bit OpenBLAS builds, both the latest stable release +# and a nightly build. +# - openblas_no_pkgconfig_fedora: +# Test OpenBLAS on Fedora. Fedora doesn't ship .pc files for OpenBLAS, +# hence this exercises the "system dependency" detection method. +# - flexiblas_fedora: +# Tests FlexiBLAS (the default on Fedora for its own packages), via +# pkg-config. FlexiBLAS allows runtime switching of BLAS/LAPACK +# libraries, which is a useful capability (not tested in this job). +# - openblas_cmake: +# Tests whether OpenBLAS LP64 is detected correctly when only CMake +# and not pkg-config is installed. +# - netlib: +# Installs vanilla blas/lapack, which is the last option tried in +# auto-detection. +# - mkl: +# Tests MKL installed from PyPI (because easiest/fastest, if broken) in +# 3 ways: both LP64 and ILP64 via pkg-config, and then using the +# Single Dynamic Library (SDL, or `libmkl_rt`). +# - blis: +# Simple test for LP64 via pkg-config +# - atlas: +# Simple test for LP64 via pkg-config on: pull_request: @@ -71,3 +103,253 @@ jobs: export NPY_RUN_MYPY_IN_TESTSUITE=1 pip install pytest pytest-xdist hypothesis typing_extensions spin test -j auto + + + openblas_no_pkgconfig_fedora: + if: "github.repository == 'numpy/numpy'" + runs-on: ubuntu-latest + container: fedora:39 + name: "OpenBLAS (Fedora, no pkg-config, LP64/ILP64)" + steps: + - name: Install system dependencies + run: | + dnf install git gcc-gfortran g++ python3-devel openblas-devel -y + + - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0 + with: + submodules: recursive + fetch-depth: 0 + + - name: Install dependencies + run: | + pip install -r build_requirements.txt + pip install pytest hypothesis typing_extensions + + - name: Build (LP64) + run: spin build -- -Dblas=openblas -Dlapack=openblas -Ddisable-optimization=true + + - name: Test + run: spin test -- numpy/linalg + + - name: Build (ILP64) + run: | + rm -rf build + spin build -- -Duse-ilp64=true -Ddisable-optimization=true + + - name: Test + run: spin test -- numpy/linalg + + + flexiblas_fedora: + if: "github.repository == 'numpy/numpy'" + runs-on: ubuntu-latest + container: fedora:39 + name: "FlexiBLAS (LP64, ILP64 on Fedora)" + steps: + - name: Install system dependencies + run: | + dnf install git gcc-gfortran g++ python3-devel flexiblas-devel -y + + - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0 + with: + submodules: recursive + fetch-depth: 0 + + - name: Install dependencies + run: | + pip install -r build_requirements.txt + pip install pytest hypothesis typing_extensions + + - name: Build + run: spin build -- -Ddisable-optimization=true + + - name: Test + run: spin test -- numpy/linalg + + - name: Build (ILP64) + run: | + rm -rf build + spin build -- -Ddisable-optimization=true -Duse-ilp64=true + + - name: Test (ILP64) + run: spin test -- numpy/linalg + + + openblas_cmake: + if: "github.repository == 'numpy/numpy'" + runs-on: ubuntu-latest + name: "OpenBLAS with CMake" + steps: + - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0 + with: + submodules: recursive + fetch-depth: 0 + - uses: actions/setup-python@61a6322f88396a6271a6ee3565807d608ecaddd1 # v4.7.0 + with: + python-version: '3.11' + + - name: Install dependencies + run: | + pip install -r build_requirements.txt + pip install pytest pytest-xdist hypothesis typing_extensions + sudo apt-get install libopenblas-dev cmake + sudo apt-get remove pkg-config + + - name: Build + run: spin build -- -Ddisable-optimization=true + + - name: Test + run: spin test -j auto -- numpy/linalg + + + netlib: + if: "github.repository == 'numpy/numpy'" + runs-on: ubuntu-latest + name: "Netlib BLAS/LAPACK" + steps: + - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0 + with: + submodules: recursive + fetch-depth: 0 + - uses: actions/setup-python@61a6322f88396a6271a6ee3565807d608ecaddd1 # v4.7.0 + with: + python-version: '3.11' + + - name: Install dependencies + run: | + pip install -r build_requirements.txt + sudo apt-get install liblapack-dev pkg-config + + - name: Build + run: | + spin build -- -Ddisable-optimization=true + + - name: Test + run: | + pip install pytest pytest-xdist hypothesis typing_extensions + spin test -j auto -- numpy/linalg + + + mkl: + if: "github.repository == 'numpy/numpy'" + runs-on: ubuntu-latest + name: "MKL (LP64, ILP64, SDL)" + steps: + - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0 + with: + submodules: recursive + fetch-depth: 0 + - uses: actions/setup-python@61a6322f88396a6271a6ee3565807d608ecaddd1 # v4.7.0 + with: + python-version: '3.11' + + - name: Install dependencies + run: | + pip install -r build_requirements.txt + pip install pytest pytest-xdist hypothesis typing_extensions + pip install mkl mkl-devel + + - name: Repair MKL pkg-config files and symlinks + run: | + # MKL 2023.2 works when installed from conda-forge (except for `-iomp` + # and `-tbb` pkg-config files), Spack, or with the standalone Intel + # installer. The standalone installer is the worst option, since it's + # large and clumsy to install and requires running a setvars.sh script + # before things work. The PyPI MKL packages are broken and need the + # fixes in this step. For details, see + # https://github.com/conda-forge/intel_repack-feedstock/issues/34 + cd $Python3_ROOT_DIR/lib/pkgconfig + sed -i 's/\/intel64//g' mkl*.pc + # add the expected .so -> .so.2 symlinks to fix linking + cd .. + for i in $( ls libmkl*.so.2 ); do ln -s $i ${i%.*}; done + + - name: Build with defaults (LP64) + run: | + pkg-config --libs mkl-dynamic-lp64-seq # check link flags + spin build -- -Ddisable-optimization=true + + - name: Test + run: spin test -- numpy/linalg + + - name: Build with ILP64 + run: | + git clean -xdf > /dev/null + pkg-config --libs mkl-dynamic-ilp64-seq + spin build -- -Duse-ilp64=true -Ddisable-optimization=true + + - name: Test + run: spin test -- numpy/linalg + + - name: Build without pkg-config (default options, SDL) + run: | + git clean -xdf > /dev/null + pushd $Python3_ROOT_DIR/lib/pkgconfig + rm mkl*.pc + popd + export MKLROOT=$Python3_ROOT_DIR + spin build -- -Ddisable-optimization=true + + - name: Test + run: spin test -- numpy/linalg + + blis: + if: "github.repository == 'numpy/numpy'" + runs-on: ubuntu-latest + name: "BLIS" + steps: + - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0 + with: + submodules: recursive + fetch-depth: 0 + - uses: actions/setup-python@61a6322f88396a6271a6ee3565807d608ecaddd1 # v4.7.0 + with: + python-version: '3.11' + + - name: Install dependencies + run: | + pip install -r build_requirements.txt + pip install pytest pytest-xdist hypothesis typing_extensions + sudo apt-get install libblis-dev libopenblas-dev pkg-config + + - name: Add BLIS pkg-config file + run: | + # Needed because blis.pc missing in Debian: + # https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=989076 + # The alternative here would be to use another distro or Miniforge + sudo cp tools/ci/_blis_debian.pc /usr/lib/x86_64-linux-gnu/pkgconfig/blis.pc + # Check if the patch works: + pkg-config --libs blis + pkg-config --cflags blis + + - name: Build + run: spin build -- -Dblas=blis -Ddisable-optimization=true + + - name: Test + run: spin test -- numpy/linalg + + atlas: + if: "github.repository == 'numpy/numpy'" + runs-on: ubuntu-latest + name: "ATLAS" + steps: + - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0 + with: + submodules: recursive + fetch-depth: 0 + - uses: actions/setup-python@61a6322f88396a6271a6ee3565807d608ecaddd1 # v4.7.0 + with: + python-version: '3.11' + + - name: Install dependencies + run: | + pip install -r build_requirements.txt + pip install pytest pytest-xdist hypothesis typing_extensions + sudo apt-get install libatlas-base-dev pkg-config + + - name: Build + run: spin build -- -Dblas=blas-atlas -Dlapack=lapack-atlas -Ddisable-optimization=true + + - name: Test + run: spin test -- numpy/linalg + diff --git a/.github/workflows/linux_musl.yml b/.github/workflows/linux_musl.yml index 593549485ba0..890a0b0e046d 100644 --- a/.github/workflows/linux_musl.yml +++ b/.github/workflows/linux_musl.yml @@ -33,12 +33,12 @@ jobs: # using git commands to clone because versioneer doesn't work when # actions/checkout is used for the clone step in a container - git config --global --add safe.directory $PWD - + git config --global --add safe.directory $PWD + if [ $GITHUB_EVENT_NAME != pull_request ]; then git clone --recursive --branch=$GITHUB_REF_NAME https://github.com/${GITHUB_REPOSITORY}.git $GITHUB_WORKSPACE git reset --hard $GITHUB_SHA - else + else git clone --recursive https://github.com/${GITHUB_REPOSITORY}.git $GITHUB_WORKSPACE git fetch origin $GITHUB_REF:my_ref_name git checkout $GITHUB_BASE_REF @@ -54,14 +54,14 @@ jobs: source test_env/bin/activate # required for figuring out the system tags in openblas_support - pip install packaging - + pip install packaging + # install openblas by co-opting the CIBW setup script RUNNER_OS=Linux sh tools/wheels/cibw_before_build.sh . pip install -r build_requirements.txt pip install pytest pytest-xdist hypothesis typing_extensions - # use meson to build and test - spin build + # use meson to build and test + spin build --with-scipy-openblas=64 -- -Duse-ilp64=true spin test -j auto diff --git a/.github/workflows/macos.yml b/.github/workflows/macos.yml index 29f141b10f9d..b34c86bec901 100644 --- a/.github/workflows/macos.yml +++ b/.github/workflows/macos.yml @@ -100,7 +100,7 @@ jobs: ccache -s accelerate: - name: Accelerate ILP64 + name: Accelerate (LP64, ILP64) if: "github.repository == 'numpy/numpy'" runs-on: macos-13 steps: @@ -122,14 +122,15 @@ jobs: pip install -r build_requirements.txt pip install pytest pytest-xdist hypothesis - - name: Build NumPy against Accelerate (ILP64) - run: | - spin build -- -Dblas=accelerate -Dlapack=accelerate -Duse-ilp64=true + - name: Build against Accelerate (LP64) + run: spin build -- -Ddisable-optimization=true - - name: Show meson-log.txt - if: always() - run: 'cat build/meson-logs/meson-log.txt' + - name: Test (linalg only) + run: spin test -j2 -- numpy/linalg - - name: Test + - name: Build NumPy against Accelerate (ILP64) run: | - spin test -j2 + spin build -- -Duse-ilp64=true + + - name: Test (fast tests) + run: spin test -j2 diff --git a/azure-steps-windows.yml b/azure-steps-windows.yml index 3fa6b18dc108..1cae980b4368 100644 --- a/azure-steps-windows.yml +++ b/azure-steps-windows.yml @@ -42,7 +42,10 @@ steps: python -m pip install . -v -Csetup-args="--vsenv" -Csetup-args="-Dblas=none" -Csetup-args="-Dlapack=none" -Csetup-args="-Dallow-noblas=true" } elseif ( Test-Path env:NPY_USE_BLAS_ILP64 ) { - python -m pip install . -v -Csetup-args="--vsenv" -Csetup-args="-Duse-ilp64=true" -Csetup-args="-Dblas-symbol-suffix=64_" + python -m pip install scipy-openblas64 spin + spin config-openblas --with-scipy-openblas=64 + $env:PKG_CONFIG_PATH="$pwd/.openblas" + python -m pip install . -v -Csetup-args="--vsenv" -Csetup-args="-Duse-ilp64=true" } else { python -m pip install . -v -Csetup-args="--vsenv" } diff --git a/build_requirements.txt b/build_requirements.txt index 7f598f623252..b1cfe0e68f49 100644 --- a/build_requirements.txt +++ b/build_requirements.txt @@ -2,5 +2,5 @@ meson-python>=0.13.1 Cython>=3.0 wheel==0.38.1 ninja -spin==0.5 +spin==0.7 build diff --git a/meson.build b/meson.build index 9ba86f393d6d..264160d132eb 100644 --- a/meson.build +++ b/meson.build @@ -12,8 +12,6 @@ project( 'b_ndebug=if-release', 'c_std=c99', 'cpp_std=c++17', - 'blas=openblas', - 'lapack=openblas', 'pkgconfig.relocatable=true', ], ) diff --git a/meson_options.txt b/meson_options.txt index 8b1fad6c4041..05e9e733578e 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -1,13 +1,19 @@ -option('blas', type: 'string', value: 'openblas', - description: 'Option for BLAS library switching') -option('lapack', type: 'string', value: 'openblas', - description: 'Option for LAPACK library switching') +option('blas', type: 'string', value: 'auto', + description: 'Option for BLAS library selection. By default, try to find any in the order given by `blas-order`') +option('lapack', type: 'string', value: 'auto', + description: 'Option for LAPACK library selection. By default, try to find any in the order given by `lapack-order`') option('allow-noblas', type: 'boolean', value: false, description: 'If set to true, allow building with (slow!) internal fallback routines') +option('blas-order', type: 'array', + value: ['mkl', 'accelerate', 'openblas', 'flexiblas', 'blis', 'blas']) +option('lapack-order', type: 'array', + value: ['mkl', 'accelerate', 'openblas', 'flexiblas', 'lapack']) option('use-ilp64', type: 'boolean', value: false, description: 'Use ILP64 (64-bit integer) BLAS and LAPACK interfaces') -option('blas-symbol-suffix', type: 'string', value: '', - description: 'BLAS and LAPACK symbol suffix to use, if any (often `64_` for ILP64)') +option('blas-symbol-suffix', type: 'string', value: 'auto', + description: 'BLAS and LAPACK symbol suffix to use, if any') +option('mkl-threading', type: 'string', value: 'auto', + description: 'MKL threading method, one of: `seq`, `iomp`, `gomp`, `tbb`') option('disable-svml', type: 'boolean', value: false, description: 'Disable building against SVML') option('disable-threading', type: 'boolean', value: false, diff --git a/numpy/core/src/common/npy_cblas.h b/numpy/core/src/common/npy_cblas.h index dad9599f605e..596a7c68cedd 100644 --- a/numpy/core/src/common/npy_cblas.h +++ b/numpy/core/src/common/npy_cblas.h @@ -57,8 +57,21 @@ enum CBLAS_SIDE {CblasLeft=141, CblasRight=142}; #define BLAS_FUNC_CONCAT(name,prefix,suffix,suffix2) prefix ## name ## suffix ## suffix2 #define BLAS_FUNC_EXPAND(name,prefix,suffix,suffix2) BLAS_FUNC_CONCAT(name,prefix,suffix,suffix2) -#define CBLAS_FUNC(name) BLAS_FUNC_EXPAND(name,BLAS_SYMBOL_PREFIX,,BLAS_SYMBOL_SUFFIX) +/* + * Use either the OpenBLAS scheme with the `64_` suffix behind the Fortran + * compiler symbol mangling, or the MKL scheme (and upcoming + * reference-lapack#666) which does it the other way around and uses `_64`. + */ +#ifdef OPENBLAS_ILP64_NAMING_SCHEME #define BLAS_FUNC(name) BLAS_FUNC_EXPAND(name,BLAS_SYMBOL_PREFIX,BLAS_FORTRAN_SUFFIX,BLAS_SYMBOL_SUFFIX) +#else +#define BLAS_FUNC(name) BLAS_FUNC_EXPAND(name,BLAS_SYMBOL_PREFIX,BLAS_SYMBOL_SUFFIX,BLAS_FORTRAN_SUFFIX) +#endif +/* + * Note that CBLAS doesn't include Fortran compiler symbol mangling, so ends up + * being the same in both schemes + */ +#define CBLAS_FUNC(name) BLAS_FUNC_EXPAND(name,BLAS_SYMBOL_PREFIX,,BLAS_SYMBOL_SUFFIX) #ifdef HAVE_BLAS_ILP64 #define CBLAS_INT npy_int64 diff --git a/numpy/meson.build b/numpy/meson.build index 150257d5b8b3..afeae9c2cc11 100644 --- a/numpy/meson.build +++ b/numpy/meson.build @@ -48,23 +48,18 @@ else ] endif -macOS13_3_or_later = false -if host_machine.system() == 'darwin' - r = run_command('xcrun', '-sdk', 'macosx', '--show-sdk-version', check: true) - sdkVersion = r.stdout().strip() - - macOS13_3_or_later = sdkVersion.version_compare('>=13.3') -endif - +blas_name = get_option('blas') +lapack_name = get_option('lapack') +allow_noblas = get_option('allow-noblas') # This is currently injected directly into CFLAGS/CXXFLAGS for wheel builds # (see cibuildwheel settings in pyproject.toml), but used by CI jobs already blas_symbol_suffix = get_option('blas-symbol-suffix') use_ilp64 = get_option('use-ilp64') if not use_ilp64 + # TODO: clean this up # For now, keep supporting the `NPY_USE_BLAS_ILP64` environment variable too - # (same as in setup.py) `false is the default for the CLI flag, so check if - # env var was set + # `false` is the default for the CLI flag, so check if env var was set use_ilp64 = run_command(py, [ '-c', @@ -74,130 +69,97 @@ if not use_ilp64 ).stdout().strip() == '1' endif +if use_ilp64 + blas_interface = ['interface: ilp64'] +else + blas_interface = ['interface: lp64'] +endif -# TODO: 64-bit (ILP64) BLAS and LAPACK support (e.g., check for more .pc files -# so we detect `openblas64_.so` directly). Partially supported now, needs more -# auto-detection. -# -# Note that this works as long as BLAS and LAPACK are detected properly via -# pkg-config. By default we look for OpenBLAS, other libraries can be configured via -# `meson configure -Dblas=blas -Dlapack=lapack` (example to build with Netlib -# BLAS and LAPACK). -# For MKL and for auto-detecting one of multiple libs, we'll need a custom -# dependency in Meson (like is done for scalapack) - see -# https://github.com/mesonbuild/meson/issues/2835 -blas_name = get_option('blas') -lapack_name = get_option('lapack') +# MKL-specific options +_threading_opt = get_option('mkl-threading') +if _threading_opt == 'auto' + # Switch default to iomp once conda-forge missing openmp.pc issue is fixed + mkl_opts = ['threading: seq'] +else + mkl_opts = ['threading: ' + _threading_opt] +endif +blas_opts = {'mkl': mkl_opts} +mkl_version_req = '>=2023.0' # see gh-24824 +mkl_may_use_sdl = not use_ilp64 and _threading_opt in ['auto', 'iomp'] -# pkg-config uses a lower-case name while CMake uses a capitalized name, so try -# that too to make the fallback detection with CMake work -if blas_name == 'openblas' - if use_ilp64 - _openblas_names = ['openblas64', 'openblas', 'OpenBLAS'] - else - _openblas_names = ['openblas', 'OpenBLAS'] +# Note that we can only use a BLAS which provides a CBLAS interface. So disable +# BLAS completely if CBLAS is not found. + +# First try scipy-openblas, and if found don't look for cblas or lapack, we +# know what's inside the scipy-openblas wheels already. +if blas_name == 'openblas' or blas_name == 'auto' + blas = dependency('scipy-openblas', required: false) + if blas.found() + blas_name = 'scipy-openblas' endif - blas = dependency(_openblas_names, required: false) -elif blas_name.to_lower() == 'accelerate' - # macOS 13.3+ has updated interfaces aligned with BLAS/LAPACK 3.9.1. Use them if available. - if macOS13_3_or_later - accelerate_compile_args = ['-DACCELERATE_NEW_LAPACK'] - if(use_ilp64) - accelerate_compile_args += '-DACCELERATE_LAPACK_ILP64' +endif +if blas_name == 'auto' + foreach _name : get_option('blas-order') + if _name == 'mkl' + blas = dependency('mkl', + modules: ['cblas'] + blas_interface + mkl_opts, + required: false, # may be required, but we need to emit a custom error message + version: mkl_version_req, + ) + # Insert a second try with MKL, because we may be rejecting older versions + # or missing it because no pkg-config installed. If so, we need to retry + # with MKL SDL, and drop the version constraint (this always worked). + if not blas.found() and mkl_may_use_sdl + blas = dependency('mkl', modules: ['cblas', 'sdl: true'], required: false) + endif + else + if _name == 'flexiblas' and use_ilp64 + _name = 'flexiblas64' + endif + blas = dependency(_name, modules: ['cblas'] + blas_interface, required: false) endif - blas = declare_dependency( - compile_args: accelerate_compile_args, - dependencies: dependency('Accelerate') - ) - else - if(use_ilp64) - error('macOS SDK 13.3+ is required for ILP64 support.') + if blas.found() + break endif - blas = dependency('Accelerate') - endif + endforeach else - blas = dependency(blas_name, required: false) -endif -have_blas = blas.found() -cblas = [] -if have_blas - # As noted above, at this point the BLAS_SYMBOL_SUFFIX may be injected into - # the CFLAGS directly, so this requires care to use that when it happens: - if blas_symbol_suffix != '' - probe_args = ['-DBLAS_SYMBOL_SUFFIX=' + blas_symbol_suffix] - else - probe_args = [] - endif - - # Netlib BLAS has a separate `libcblas.so` which we use directly in the g77 - # ABI wrappers, so detect it and error out if we cannot find it. OpenBLAS can - # be built without CBLAS too (see gh-23909, done by Arch Linux until - # recently) - # In the future, this should be done automatically for: - # `dependency('blas', modules: cblas)` - # see https://github.com/mesonbuild/meson/pull/10921. - have_cblas = false - if blas_name.to_lower() == 'accelerate' - _cblas_header = '' - elif blas_name.to_lower().startswith('mkl') - _cblas_header = '' - else - _cblas_header = '' - endif - if cc.links(f''' - #ifndef BLAS_SYMBOL_SUFFIX - # define BLAS_SYMBOL_SUFFIX - #endif - #define EXPAND(suffix) cblas_ddot ## suffix - #define DDOT(suffix) EXPAND(suffix) - - #include @_cblas_header@ - - int main(int argc, const char *argv[]) - { - double a[4] = {1,2,3,4}; - double b[4] = {5,6,7,8}; - return DDOT(BLAS_SYMBOL_SUFFIX)(4, a, 1, b, 1) > 10; - } - ''', - dependencies: blas, - args: probe_args, - name: 'CBLAS', + if blas_name == 'mkl' + blas = dependency('mkl', + modules: ['cblas'] + blas_interface + mkl_opts, + required: false, + version: mkl_version_req, ) - have_cblas = true - else - cblas = dependency('cblas', required: false) - if cblas.found() - have_cblas = true + # Same deal as above - try again for MKL + if not blas.found() and mkl_may_use_sdl + blas = dependency('mkl', modules: ['cblas', 'sdl: true'], required: false) endif + else + blas = dependency(blas_name, modules: ['cblas'] + blas_interface, required: false) endif endif -# BLAS and LAPACK are dependencies for NumPy. Since NumPy 2.0, by default the -# build will fail if they are missing; the performance impact is large, so -# using fallback routines must be explicitly opted into by the user. xref -# gh-24200 for a discussion on this. -# -# Note that we can only use a BLAS which provides a CBLAS interface. So disable -# BLAS completely if CBLAS is not found. -allow_noblas = get_option('allow-noblas') +have_blas = blas.found() if have_blas - _args_blas = [] # note: used for C and C++ via `blas_dep` below - if have_cblas - _args_blas += ['-DHAVE_CBLAS'] - elif not allow_noblas - error('No CBLAS interface detected! Install a BLAS library with CBLAS ' + \ - 'support, or use the `allow-noblas` build option (note, this ' + \ - 'may be up to 100x slower for some linear algebra operations).') - endif + _args_blas = ['-DHAVE_CBLAS'] # note: used for C and C++ via `blas_dep` below if use_ilp64 _args_blas += ['-DHAVE_BLAS_ILP64'] + if 'openblas' in blas.name() + _args_blas += ['-DOPENBLAS_ILP64_NAMING_SCHEME'] + endif + endif + if blas_symbol_suffix == 'auto' + if blas_name == 'scipy-openblas' and use_ilp64 + blas_symbol_suffix = '64_' + else + blas_symbol_suffix = blas.get_variable('symbol_suffix', default_value: '') + endif + message(f'BLAS symbol suffix: @blas_symbol_suffix@') endif if blas_symbol_suffix != '' _args_blas += ['-DBLAS_SYMBOL_SUFFIX=' + blas_symbol_suffix] endif blas_dep = declare_dependency( - dependencies: [blas, cblas], + dependencies: [blas], compile_args: _args_blas, ) else @@ -210,35 +172,33 @@ else endif endif -if lapack_name == 'openblas' - lapack_dep = dependency(['openblas', 'OpenBLAS'], required: false) -elif lapack_name.to_lower() == 'accelerate' - # macOS 13.3+ has updated interfaces aligned with BLAS/LAPACK 3.9.1. Use them if available. - if macOS13_3_or_later - accelerate_compile_args = ['-DACCELERATE_NEW_LAPACK'] - if(use_ilp64) - accelerate_compile_args += '-DACCELERATE_LAPACK_ILP64' - endif - lapack_dep = declare_dependency( - compile_args: accelerate_compile_args, - dependencies: dependency('Accelerate') - ) +if 'mkl' in blas.name() or blas.name() == 'accelerate' or blas_name == 'scipy-openblas' + # For these libraries we know that they contain LAPACK, and it's desirable to + # use that - no need to run the full detection twice. + lapack = blas +else + if lapack_name == 'auto' + foreach _name : get_option('lapack-order') + lapack = dependency(_name, modules: ['lapack'] + blas_interface, required: false) + if lapack.found() + break + endif + endforeach else - if(use_ilp64) - error('macOS SDK 13.3+ is required for ILP64 support.') - endif - lapack_dep = dependency('Accelerate') + lapack = dependency(lapack_name, modules: ['lapack'] + blas_interface, required: false) endif -else - lapack_dep = dependency(lapack_name, required: false) endif -have_lapack = lapack_dep.found() + +have_lapack = lapack.found() if not have_lapack and not allow_noblas error('No LAPACK library detected! Install one, or use the ' + \ '`allow-noblas` build option (note, this may be up to 100x slower ' + \ 'for some linear algebra operations).') +else + lapack_dep = declare_dependency(dependencies: [lapack, blas_dep]) endif + # Copy the main __init__.py|pxd files to the build dir (needed for Cython) __init__py = fs.copyfile('__init__.py') __init__pxd = fs.copyfile('__init__.pxd') @@ -377,7 +337,7 @@ conf_data.set('PYTHON_VERSION', py.language_version()) dependency_map = { 'LAPACK': lapack_dep, } -if have_blas and have_cblas +if have_blas dependency_map += {'BLAS': blas} else conf_data.set('BLAS_NAME', blas_name) @@ -391,13 +351,11 @@ foreach name, dep : dependency_map if dep.found() conf_data.set(name + '_VERSION', dep.version()) conf_data.set(name + '_TYPE_NAME', dep.type_name()) - if dep.type_name() == 'pkgconfig' - # CMake detection yields less info, so we need to leave it blank there - conf_data.set(name + '_INCLUDEDIR', dep.get_variable('includedir')) - conf_data.set(name + '_LIBDIR', dep.get_variable('libdir')) - conf_data.set(name + '_OPENBLAS_CONFIG', dep.get_variable('openblas_config')) - conf_data.set(name + '_PCFILEDIR', dep.get_variable('pcfiledir')) - endif + # get_variable() results may be missing for a variety of reasons + conf_data.set(name + '_INCLUDEDIR', dep.get_variable('includedir', default_value: 'unknown')) + conf_data.set(name + '_LIBDIR', dep.get_variable('libdir', default_value: 'unknown')) + conf_data.set(name + '_OPENBLAS_CONFIG', dep.get_variable('openblas_config', default_value: 'unknown')) + conf_data.set(name + '_PCFILEDIR', dep.get_variable('pcfiledir', default_value: 'unknown')) endif endforeach diff --git a/pyproject.toml b/pyproject.toml index c8620c90f4e7..4cbe74221c9e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -152,6 +152,7 @@ tracker = "https://github.com/numpy/numpy/issues" skip = "cp36-* cp37-* cp-38* pp37-* pp38-* *-manylinux_i686 *_ppc64le *_s390x *-musllinux_aarch64" build-verbosity = "3" before-build = "bash {project}/tools/wheels/cibw_before_build.sh {project}" +config-settings = "setup-args=-Duse-ilp64=true setup-args=-Dblas=openblas setup-args=-Dlapack=openblas setup-args=-Dblas-symbol-suffix=64_" # meson has a hard dependency on ninja, and we need meson to build # c-extensions in tests. There is a ninja PyPI package used in # build_requirements.txt for macOS, windows, linux but it cannot be in @@ -164,7 +165,7 @@ test-command = "bash {project}/tools/wheels/cibw_test_command.sh {project}" manylinux-x86_64-image = "manylinux2014" manylinux-aarch64-image = "manylinux2014" musllinux-x86_64-image = "musllinux_1_1" -environment = { CFLAGS="-fno-strict-aliasing -DBLAS_SYMBOL_SUFFIX=64_ -DHAVE_BLAS_ILP64", LDFLAGS="-Wl,--strip-debug", CXXFLAGS="-DBLAS_SYMBOL_SUFFIX=64_ -DHAVE_BLAS_ILP64", NPY_USE_BLAS_ILP64="1", RUNNER_OS="Linux"} +environment = {CFLAGS="-fno-strict-aliasing", LDFLAGS="-Wl,--strip-debug", NPY_USE_BLAS_ILP64="1", RUNNER_OS="Linux"} [tool.cibuildwheel.macos] # For universal2 wheels, we will need to fuse them manually @@ -174,12 +175,13 @@ environment = { CFLAGS="-fno-strict-aliasing -DBLAS_SYMBOL_SUFFIX=64_ -DHAVE_BLA # for more info archs = "x86_64 arm64" test-skip = "*_universal2:arm64" -# MACOS linker doesn't support stripping symbols -environment = {CFLAGS="-fno-strict-aliasing -DBLAS_SYMBOL_SUFFIX=64_ -DHAVE_BLAS_ILP64", CXXFLAGS="-DBLAS_SYMBOL_SUFFIX=64_ -DHAVE_BLAS_ILP64", NPY_USE_BLAS_ILP64="1", CC="clang", CXX = "clang++", RUNNER_OS="macOS"} +# MACOS linker doesn't support stripping symbols. +# Note that NPY_USE_BLAS_ILP64 is used in `tools/openblas_support.py`. +environment = {CFLAGS="-fno-strict-aliasing", CC="clang", CXX = "clang++", NPY_USE_BLAS_ILP64="1", RUNNER_OS="macOS"} [tool.cibuildwheel.windows] -environment = {NPY_USE_BLAS_ILP64="1", CFLAGS="-DBLAS_SYMBOL_SUFFIX=64_ -DHAVE_BLAS_ILP64", CXXFLAGS="-DBLAS_SYMBOL_SUFFIX=64_ -DHAVE_BLAS_ILP64", LDFLAGS="", PKG_CONFIG_PATH="C:/opt/64/lib/pkgconfig"} -config-settings = "setup-args=--vsenv" +environment = {NPY_USE_BLAS_ILP64="1", PKG_CONFIG_PATH="C:/opt/64/lib/pkgconfig"} +config-settings = "setup-args=--vsenv setup-args=-Duse-ilp64=true setup-args=-Dblas=openblas setup-args=-Dlapack=openblas" repair-wheel-command = "bash ./tools/wheels/repair_windows.sh {wheel} {dest_dir}" [[tool.cibuildwheel.overrides]] diff --git a/tools/ci/_blis_debian.pc b/tools/ci/_blis_debian.pc new file mode 100644 index 000000000000..b849b50f6b1f --- /dev/null +++ b/tools/ci/_blis_debian.pc @@ -0,0 +1,8 @@ +libdir=/usr/lib/x86_64-linux-gnu/blis-pthread/ +includedir=/usr/include/x86_64-linux-gnu/blis-pthread + +Name: BLIS +Description: BLAS-like Library Instantiation Software Framework - specific to NumPy CI job, needed until Debian ships blis.pc (see .github/workflows/linux_blas.yml) +Version: 0.9.0-numpy-ci +Libs: -L${libdir} -lblis +Cflags: -I${includedir} diff --git a/vendored-meson/meson b/vendored-meson/meson index b7dc7abc4102..66ba7dbbfe28 160000 --- a/vendored-meson/meson +++ b/vendored-meson/meson @@ -1 +1 @@ -Subproject commit b7dc7abc4102ec3db4bb9066cb5e674e7a4b08f4 +Subproject commit 66ba7dbbfe2838983f65ad8fe16da1535ebf5b9d From 34ea7a8b75f46b139a6afe46bba3a9ffd4ee5a68 Mon Sep 17 00:00:00 2001 From: Charles Harris Date: Tue, 10 Oct 2023 16:25:36 -0600 Subject: [PATCH 2/6] MAINT: Update ``spin/cmds.py`` from main. --- .spin/cmds.py | 157 ++++++++++++++++++++------------------------------ 1 file changed, 61 insertions(+), 96 deletions(-) diff --git a/.spin/cmds.py b/.spin/cmds.py index ea994c38311e..09556e67bbce 100644 --- a/.spin/cmds.py +++ b/.spin/cmds.py @@ -37,9 +37,14 @@ "-v", "--verbose", is_flag=True, help="Print all build output, even installation" ) +@click.option( + "--with-scipy-openblas", type=click.Choice(["32", "64"]), + default=None, + help="Build with pre-installed scipy-openblas32 or scipy-openblas64 wheel" +) @click.argument("meson_args", nargs=-1) @click.pass_context -def build(ctx, meson_args, jobs=None, clean=False, verbose=False): +def build(ctx, meson_args, with_scipy_openblas, jobs=None, clean=False, verbose=False, quiet=False): """🔧 Build package with Meson/ninja and install MESON_ARGS are passed through e.g.: @@ -53,6 +58,10 @@ def build(ctx, meson_args, jobs=None, clean=False, verbose=False): CFLAGS="-O0 -g" spin build """ + # XXX keep in sync with upstream build + if with_scipy_openblas: + _config_openblas(with_scipy_openblas) + ctx.params.pop("with_scipy_openblas", None) ctx.forward(meson.build) @@ -187,51 +196,6 @@ def test(ctx, pytest_args, markexpr, n_jobs, tests, verbose): ctx.forward(meson.test) -@click.command() -@click.option('--code', '-c', help='Python program passed in as a string') -@click.argument('gdb_args', nargs=-1) -def gdb(code, gdb_args): - """👾 Execute a Python snippet with GDB - - spin gdb -c 'import numpy as np; print(np.__version__)' - - Or pass arguments to gdb: - - spin gdb -c 'import numpy as np; print(np.__version__)' -- --fullname - - Or run another program, they way you normally would with gdb: - - \b - spin gdb ls - spin gdb -- --args ls -al - - You can also run Python programs: - - \b - spin gdb my_tests.py - spin gdb -- my_tests.py --mytest-flag - """ - meson._set_pythonpath() - gdb_args = list(gdb_args) - - if gdb_args and gdb_args[0].endswith('.py'): - gdb_args = ['--args', sys.executable] + gdb_args - - if sys.version_info[:2] >= (3, 11): - PYTHON_FLAGS = ['-P'] - code_prefix = '' - else: - PYTHON_FLAGS = [] - code_prefix = 'import sys; sys.path.pop(0); ' - - if code: - PYTHON_ARGS = ['-c', code_prefix + code] - gdb_args += ['--args', sys.executable] + PYTHON_FLAGS + PYTHON_ARGS - - gdb_cmd = ['gdb', '-ex', 'set detach-on-fork on'] + gdb_args - util.run(gdb_cmd, replace=True) - - # From scipy: benchmarks/benchmarks/common.py def _set_mem_rlimit(max_mem=None): """ @@ -297,19 +261,7 @@ def _run_asv(cmd): except (ImportError, RuntimeError): pass - try: - util.run(cmd, cwd='benchmarks', env=env, sys_exit=False) - except FileNotFoundError: - click.secho(( - "Cannot find `asv`. " - "Please install Airspeed Velocity:\n\n" - " https://asv.readthedocs.io/en/latest/installing.html\n" - "\n" - "Depending on your system, one of the following should work:\n\n" - " pip install asv\n" - " conda install asv\n" - ), fg="red") - sys.exit(1) + util.run(cmd, cwd='benchmarks', env=env) @click.command() @@ -330,13 +282,17 @@ def _run_asv(cmd): @click.option( '--verbose', '-v', is_flag=True, default=False ) +@click.option( + '--quick', '-q', is_flag=True, default=False, + help="Run each benchmark only once (timings won't be accurate)" +) @click.argument( 'commits', metavar='', required=False, nargs=-1 ) @click.pass_context -def bench(ctx, tests, compare, verbose, commits): +def bench(ctx, tests, compare, verbose, quick, commits): """🏋 Run benchmarks. \b @@ -376,6 +332,9 @@ def bench(ctx, tests, compare, verbose, commits): if verbose: bench_args = ['-v'] + bench_args + if quick: + bench_args = ['--quick'] + bench_args + if not compare: # No comparison requested; we build and benchmark the current version @@ -403,27 +362,21 @@ def bench(ctx, tests, compare, verbose, commits): cmd = [ 'asv', 'run', '--dry-run', '--show-stderr', '--python=same' ] + bench_args - _run_asv(cmd) - else: - # Benchmark comparison - # Ensure that we don't have uncommited changes commit_a, commit_b = [_commit_to_sha(c) for c in commits] - if commit_b == 'HEAD': - if _dirty_git_working_dir(): - click.secho( - "WARNING: you have uncommitted changes --- " - "these will NOT be benchmarked!", - fg="red" - ) + if commit_b == 'HEAD' and _dirty_git_working_dir(): + click.secho( + "WARNING: you have uncommitted changes --- " + "these will NOT be benchmarked!", + fg="red" + ) cmd_compare = [ 'asv', 'continuous', '--factor', '1.05', ] + bench_args + [commit_a, commit_b] - _run_asv(cmd_compare) @@ -441,7 +394,6 @@ def python(ctx, python_args): """ env = os.environ env['PYTHONWARNINGS'] = env.get('PYTHONWARNINGS', 'all') - ctx.invoke(build) ctx.forward(meson.python) @@ -472,29 +424,6 @@ def ipython(ctx, ipython_args): list(ipython_args)) -@click.command(context_settings={"ignore_unknown_options": True}) -@click.argument("args", nargs=-1) -@click.pass_context -def run(ctx, args): - """🏁 Run a shell command with PYTHONPATH set - - \b - spin run make - spin run 'echo $PYTHONPATH' - spin run python -c 'import sys; del sys.path[0]; import mypkg' - - If you'd like to expand shell variables, like `$PYTHONPATH` in the example - above, you need to provide a single, quoted command to `run`: - - spin run 'echo $SHELL && echo $PWD' - - On Windows, all shell commands are run via Bash. - Install Git for Windows if you don't have Bash already. - """ - ctx.invoke(build) - ctx.forward(meson.run) - - @click.command(context_settings={"ignore_unknown_options": True}) @click.pass_context def mypy(ctx): @@ -505,3 +434,39 @@ def mypy(ctx): ctx.params['pytest_args'] = [os.path.join('numpy', 'typing')] ctx.params['markexpr'] = 'full' ctx.forward(test) + +@click.command(context_settings={ + 'ignore_unknown_options': True +}) +@click.option( + "--with-scipy-openblas", type=click.Choice(["32", "64"]), + default=None, required=True, + help="Build with pre-installed scipy-openblas32 or scipy-openblas64 wheel" +) +def config_openblas(with_scipy_openblas): + """🔧 Create .openblas/scipy-openblas.pc file + + Also create _distributor_init_local.py + + Requires a pre-installed scipy-openblas64 or scipy-openblas32 + """ + _config_openblas(with_scipy_openblas) + + +def _config_openblas(blas_variant): + import importlib + basedir = os.getcwd() + openblas_dir = os.path.join(basedir, ".openblas") + pkg_config_fname = os.path.join(openblas_dir, "scipy-openblas.pc") + if blas_variant: + module_name = f"scipy_openblas{blas_variant}" + try: + openblas = importlib.import_module(module_name) + except ModuleNotFoundError: + raise RuntimeError(f"'pip install {module_name} first") + local = os.path.join(basedir, "numpy", "_distributor_init_local.py") + with open(local, "wt", encoding="utf8") as fid: + fid.write(f"import {module_name}\n") + os.makedirs(openblas_dir, exist_ok=True) + with open(pkg_config_fname, "wt", encoding="utf8") as fid: + fid.write(openblas.get_pkg_config().replace("\\", "/")) From 5134f9aa830edbbc2585aabfa70a977fce11068e Mon Sep 17 00:00:00 2001 From: Charles Harris Date: Tue, 10 Oct 2023 17:38:17 -0600 Subject: [PATCH 3/6] MAINT: Use `linux_musl.yml` from main. --- .github/workflows/linux_musl.yml | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/.github/workflows/linux_musl.yml b/.github/workflows/linux_musl.yml index 890a0b0e046d..5c65a2b2e8b9 100644 --- a/.github/workflows/linux_musl.yml +++ b/.github/workflows/linux_musl.yml @@ -33,12 +33,12 @@ jobs: # using git commands to clone because versioneer doesn't work when # actions/checkout is used for the clone step in a container - git config --global --add safe.directory $PWD - + git config --global --add safe.directory $PWD + if [ $GITHUB_EVENT_NAME != pull_request ]; then git clone --recursive --branch=$GITHUB_REF_NAME https://github.com/${GITHUB_REPOSITORY}.git $GITHUB_WORKSPACE git reset --hard $GITHUB_SHA - else + else git clone --recursive https://github.com/${GITHUB_REPOSITORY}.git $GITHUB_WORKSPACE git fetch origin $GITHUB_REF:my_ref_name git checkout $GITHUB_BASE_REF @@ -48,20 +48,22 @@ jobs: ln -s /usr/local/bin/python3.10 /usr/local/bin/python - - name: test musllinux_x86_64 + - name: test-musllinux_x86_64 + env: + PKG_CONFIG_PATH: ${{ github.workspace }}/.openblas run: | python -m venv test_env source test_env/bin/activate - # required for figuring out the system tags in openblas_support - pip install packaging - - # install openblas by co-opting the CIBW setup script - RUNNER_OS=Linux sh tools/wheels/cibw_before_build.sh . + pip install scipy-openblas64 - pip install -r build_requirements.txt - pip install pytest pytest-xdist hypothesis typing_extensions + pip install -r build_requirements.txt -r test_requirements.txt - # use meson to build and test + # use meson to build and test spin build --with-scipy-openblas=64 -- -Duse-ilp64=true spin test -j auto + + - name: Meson Log + shell: bash + run: | + cat build/meson-logs/meson-log.txt From a6f9ebb7afec8e1f03fcfe6d581e1fc548529197 Mon Sep 17 00:00:00 2001 From: Charles Harris Date: Tue, 10 Oct 2023 18:15:40 -0600 Subject: [PATCH 4/6] MAINT: Update ``pyproject.toml`` --- pyproject.toml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 4cbe74221c9e..cfe077d5983a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -66,6 +66,7 @@ documentation = "https://numpy.org/doc/" source = "https://github.com/numpy/numpy" download = "https://pypi.org/project/numpy/#files" tracker = "https://github.com/numpy/numpy/issues" +"release notes" = "https://numpy.org/doc/stable/release" [tool.towncrier] # Do no set this since it is hard to import numpy inside the source directory @@ -201,10 +202,11 @@ cli = 'vendored-meson/meson/meson.py' ".spin/cmds.py:build", ".spin/cmds.py:test", ".spin/cmds.py:mypy", + ".spin/cmds.py:config_openblas", ] "Environments" = [ - ".spin/cmds.py:run", ".spin/cmds.py:ipython", - ".spin/cmds.py:python", ".spin/cmds.py:gdb" + "spin.cmds.meson.run", ".spin/cmds.py:ipython", + ".spin/cmds.py:python", "spin.cmds.meson.gdb" ] "Documentation" = [".spin/cmds.py:docs"] "Metrics" = [".spin/cmds.py:bench"] From e8aca7cdaada125453d4ff5c50bc603bb14aca7b Mon Sep 17 00:00:00 2001 From: Ralf Gommers Date: Wed, 11 Oct 2023 12:08:26 +0200 Subject: [PATCH 5/6] DEV: backport `_distributor_init.py` change to support scipy-openblas This should fix the MUSL CI job failure after the Meson auto-BLAS/LAPACK update. --- numpy/_distributor_init.py | 7 ++++++- numpy/meson.build | 4 ++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/numpy/_distributor_init.py b/numpy/_distributor_init.py index d893ba37719b..25b0eed79fca 100644 --- a/numpy/_distributor_init.py +++ b/numpy/_distributor_init.py @@ -3,8 +3,13 @@ Distributors: you can add custom code here to support particular distributions of numpy. -For example, this is a good place to put any checks for hardware requirements. +For example, this is a good place to put any BLAS/LAPACK initialization code. The numpy standard source distribution will not put code in this file, so you can safely replace this file with your own version. """ + +try: + from . import _distributor_init_local +except ImportError: + pass diff --git a/numpy/meson.build b/numpy/meson.build index afeae9c2cc11..fc10acb5eb5a 100644 --- a/numpy/meson.build +++ b/numpy/meson.build @@ -225,6 +225,10 @@ python_sources = [ 'py.typed' ] +if blas_name == 'scipy-openblas' + python_sources += ['_distributor_init_local.py'] +endif + py.install_sources( python_sources, subdir: 'numpy' From 891fb2213ca7919f48e7e7705ad1be0b681df330 Mon Sep 17 00:00:00 2001 From: Ralf Gommers Date: Wed, 11 Oct 2023 11:59:03 +0200 Subject: [PATCH 6/6] BLD: update setup.py build for changes to ILP64 build config [skip circle] [skip cirrus] --- numpy/distutils/system_info.py | 5 ++++- numpy/linalg/setup.py | 3 ++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/numpy/distutils/system_info.py b/numpy/distutils/system_info.py index edf56909ab5d..feb28f61cf07 100644 --- a/numpy/distutils/system_info.py +++ b/numpy/distutils/system_info.py @@ -2357,7 +2357,10 @@ def _calc_info(self): if self.symbol_prefix: info['define_macros'] += [('BLAS_SYMBOL_PREFIX', self.symbol_prefix)] if self.symbol_suffix: - info['define_macros'] += [('BLAS_SYMBOL_SUFFIX', self.symbol_suffix)] + info['define_macros'] += [ + ('BLAS_SYMBOL_SUFFIX', self.symbol_suffix), + ('OPENBLAS_ILP64_NAMING_SCHEME', None), + ] return info diff --git a/numpy/linalg/setup.py b/numpy/linalg/setup.py index 6f72635ab67f..e357e294f797 100644 --- a/numpy/linalg/setup.py +++ b/numpy/linalg/setup.py @@ -51,7 +51,8 @@ def calc_info(self): # but use the "64_" convention here. info['define_macros'] = [ ('HAVE_BLAS_ILP64', None), - ('BLAS_SYMBOL_SUFFIX', '64_') + ('BLAS_SYMBOL_SUFFIX', '64_'), + ('OPENBLAS_ILP64_NAMING_SCHEME', None), ] self.set_info(**info)