8000 ENH: meson: implement BLAS/LAPACK auto-detection and many CI jobs [wh… · numpy/numpy@34afbb9 · GitHub
[go: up one dir, main page]

Skip to content

Commit 34afbb9

Browse files
committed
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 8000 `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).
1 parent c294f1a commit 34afbb9

File tree

11 files changed

+423
-179
lines changed

11 files changed

+423
-179
lines changed

.github/workflows/linux_blas.yml

Lines changed: 271 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,27 @@ name: BLAS tests (Linux)
1010
# - openblas32_stable_nightly:
1111
# Uses the 32-bit OpenBLAS builds, both the latest stable release
1212
# and a nightly build.
13-
#
14-
# TODO: coverage here is limited, we should add non-OpenBLAS libraries and
15-
# exercise the BLAS-related build options (see `meson_options.txt`).
13+
# - openblas_no_pkgconfig_fedora:
14+
# Test OpenBLAS on Fedora. Fedora doesn't ship .pc files for OpenBLAS,
15+
# hence this exercises the "system dependency" detection method.
16+
# - flexiblas_fedora:
17+
# Tests FlexiBLAS (the default on Fedora for its own packages), via
18+
# pkg-config. FlexiBLAS allows runtime switching of BLAS/LAPACK
19+
# libraries, which is a useful capability (not tested in this job).
20+
# - openblas_cmake:
21+
# Tests whether OpenBLAS LP64 is detected correctly when only CMake
22+
# and not pkg-config is installed.
23+
# - netlib:
24+
# Installs vanilla blas/lapack, which is the last option tried in
25+
# auto-detection.
26+
# - mkl:
27+
# Tests MKL installed from PyPI (because easiest/fastest, if broken) in
28+
# 3 ways: both LP64 and ILP64 via pkg-config, and then using the
29+
# Single Dynamic Library (SDL, or `libmkl_rt`).
30+
# - blis:
31+
# Simple test for LP64 via pkg-config
32+
# - atlas:
33+
# Simple test for LP64 via pkg-config
1634

1735
on:
1836
pull_request:
@@ -87,3 +105,253 @@ jobs:
87105
run: |
88106
pip install pytest pytest-xdist hypothesis typing_extensions
89107
spin test -j auto
108+
109+
110+
openblas_no_pkgconfig_fedora:
111+
if: "github.repository == 'numpy/numpy'"
112+
runs-on: ubuntu-latest
113+
container: fedora:39
114+
name: "OpenBLAS (Fedora, no pkg-config, LP64/ILP64)"
115+
steps:
116+
- name: Install system dependencies
117+
run: |
118+
dnf install git gcc-gfortran g++ python3-devel openblas-devel -y
119+
120+
- uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
121+
with:
122+
submodules: recursive
123+
fetch-depth: 0
124+
125+
- name: Install dependencies
126+
run: |
127+
pip install -r build_requirements.txt
128+
pip install pytest hypothesis typing_extensions
129+
130+
- name: Build (LP64)
131+
run: spin build -- -Dblas=openblas -Dlapack=openblas -Ddisable-optimization=true
132+
133+
- name: Test
134+
run: spin test -- numpy/linalg
135+
136+
- name: Build (ILP64)
137+
run: |
138+
rm -rf build
139+
spin build -- -Duse-ilp64=true -Ddisable-optimization=true
140+
141+
- name: Test
142+
run: spin test -- numpy/linalg
143+
144+
145+
flexiblas_fedora:
146+
if: "github.repository == 'numpy/numpy'"
147+
runs-on: ubuntu-latest
148+
container: fedora:39
149+
name: "FlexiBLAS (LP64, ILP64 on Fedora)"
150+
steps:
151+
- name: Install system dependencies
152+
run: |
153+
dnf install git gcc-gfortran g++ python3-devel flexiblas-devel -y
154+
155+
- uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
156+
with:
157+
submodules: recursive
158+
fetch-depth: 0
159+
160+
- name: Install dependencies
161+
run: |
162+
pip install -r build_requirements.txt
163+
pip install pytest hypothesis typing_extensions
164+
165+
- name: Build
166+
run: spin build -- -Ddisable-optimization=true
167+
168+
- name: Test
169+
run: spin test -- numpy/linalg
170+
171+
- name: Build (ILP64)
172+
run: |
173+
rm -rf build
174+
spin build -- -Ddisable-optimization=true -Duse-ilp64=true
175+
176+
- name: Test (ILP64)
177+
run: spin test -- numpy/linalg
178+
179+
180+
openblas_cmake:
181+
if: "github.repository == 'numpy/numpy'"
182+
runs-on: ubuntu-latest
183+
name: "OpenBLAS with CMake"
184+
steps:
185+
- uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
186+
with:
187+
submodules: recursive
188+
fetch-depth: 0
189+
- uses: actions/setup-python@61a6322f88396a6271a6ee3565807d608ecaddd1 # v4.7.0
190+
with:
191+
python-version: '3.11'
192+
193+
- name: Install dependencies
194+
run: |
195+
pip install -r build_requirements.txt
196+
pip install pytest pytest-xdist hypothesis typing_extensions
197+
sudo apt-get install libopenblas-dev cmake
198+
sudo apt-get remove pkg-config
199+
200+
- name: Build
201+
run: spin build -- -Ddisable-optimization=true
202+
203+
- name: Test
204+
run: spin test -j auto -- numpy/linalg
205+
206+
207+
netlib:
208+
if: "github.repository == 'numpy/numpy'"
209+
runs-on: ubuntu-latest
210+
name: "Netlib BLAS/LAPACK"
211+
steps:
212+
- uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
213+
with:
214+
submodules: recursive
215+
fetch-depth: 0
216+
- uses: actions/setup-python@61a6322f88396a6271a6ee3565807d608ecaddd1 # v4.7.0
217+
with:
218+
python-version: '3.11'
219+
220+
- name: Install dependencies
221+
run: |
222+
pip install -r build_requirements.txt
223+
sudo apt-get install liblapack-dev pkg-config
224+
225+
- name: Build
226+
run: |
227+
spin build -- -Ddisable-optimization=true
228+
229+
- name: Test
230+
run: |
231+
pip install pytest pytest-xdist hypothesis typing_extensions
232+
spin test -j auto -- numpy/linalg
233+
234+
235+
mkl:
236+
if: "github.repository == 'numpy/numpy'"
237+
runs-on: ubuntu-latest
238+
name: "MKL (LP64, ILP64, SDL)"
239+
steps:
240+
- uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
241+
with:
242+
submodules: recursive
243+
fetch-depth: 0
244+
- uses: actions/setup-python@61a6322f88396a6271a6ee3565807d608ecaddd1 # v4.7.0
245+
with:
246+
python-version: '3.11'
247+
248+
- name: Install dependencies
249+
run: |
250+
pip install -r build_requirements.txt
251+
pip install pytest pytest-xdist hypothesis typing_extensions
252+
pip install mkl mkl-devel
253+
254+
- name: Repair MKL pkg-config files and symlinks
255+
run: |
256+
# MKL 2023.2 works when installed from conda-forge (except for `-iomp`
257+
# and `-tbb` pkg-config files), Spack, or with the standalone Intel
258+
# installer. The standalone installer is the worst option, since it's
259+
# large and clumsy to install and requires running a setvars.sh script
260+
# before things work. The PyPI MKL packages are broken and need the
261+
# fixes in this step. For details, see
262+
# https://github.com/conda-forge/intel_repack-feedstock/issues/34
263+
cd $Python3_ROOT_DIR/lib/pkgconfig
264+
sed -i 's/\/intel64//g' mkl*.pc
265+
# add the expected .so -> .so.2 symlinks to fix linking
266+
cd ..
267+
for i in $( ls libmkl*.so.2 ); do ln -s $i ${i%.*}; done
268+
269+
- name: Build with defaults (LP64)
270+
run: |
271+
pkg-config --libs mkl-dynamic-lp64-seq # check link flags
272+
spin build -- -Ddisable-optimization=true
273+
274+
- name: Test
275+
run: spin test -- numpy/linalg
276+
277+
- name: Build with ILP64
278+
run: |
279+
git clean -xdf > /dev/null
280+
pkg-config --libs mkl-dynamic-ilp64-seq
281+
spin build -- -Duse-ilp64=true -Ddisable-optimization=true
282+
283+
- name: Test
284+
run: spin test -- numpy/linalg
285+
286+
- name: Build without pkg-config (default options, SDL)
287+
run: |
288+
git clean -xdf > /dev/null
289+
pushd $Python3_ROOT_DIR/lib/pkgconfig
290+
rm mkl*.pc
291+
popd
292+
export MKLROOT=$Python3_ROOT_DIR
293+
spin build -- -Ddisable-optimization=true
294+
295+
- name: Test
296+
run: spin test -- numpy/linalg
297+
298+
blis:
299+
if: "github.repository == 'numpy/numpy'"
300+
runs-on: ubuntu-latest
301+
name: "BLIS"
302+
steps:
303+
- uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
304+
with:
305+
submodules: recursive
306+
fetch-depth: 0
307+
- uses: actions/setup-python@61a6322f88396a6271a6ee3565807d608ecaddd1 # v4.7.0
308+
with:
309+
python-version: '3.11'
310+
311+
- name: Install dependencies
312+
run: |
313+
pip install -r build_requirements.txt
314+
pip install pytest pytest-xdist hypothesis typing_extensions
315+
sudo apt-get install libblis-dev libopenblas-dev pkg-config
316+
317+
- name: Add BLIS pkg-config file
318+
run: |
319+
# Needed because blis.pc missing in Debian:
320+
# https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=989076
321+
# The alternative here would be to use another distro or Miniforge
322+
sudo cp tools/ci/_blis_debian.pc /usr/lib/x86_64-linux-gnu/pkgconfig/blis.pc
323+
# Check if the patch works:
324+
pkg-config --libs blis
325+
pkg-config --cflags blis
326+
327+
- name: Build
328+
run: spin build -- -Dblas=blis -Ddisable-optimization=true
329+
330+
- name: Test
331+
run: spin test -- numpy/linalg
332+
333+
atlas:
334+
if: "github.repository == 'numpy/numpy'"
335+
runs-on: ubuntu-latest
336+
name: "ATLAS"
337+
steps:
338+
- uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
339+
with:
340+
submodules: recursive
341+
fetch-depth: 0
342+
- uses: actions/setup-python@61a6322f88396a6271a6ee3565807d608ecaddd1 # v4.7.0
343+
with:
344+
python-version: '3.11'
345+
346+
- name: Install dependencies
347+
run: |
348+
pip install -r build_requirements.txt
349+
pip install pytest pytest-xdist hypothesis typing_extensions
350+
sudo apt-get install libatlas-base-dev pkg-config
351+
352+
- name: Build
353+
run: spin build -- -Dblas=blas-atlas -Dlapack=lapack-atlas -Ddisable-optimization=true
354+
355+
- name: Test
356+
run: spin test -- numpy/linalg
357+

.github/workflows/linux_musl.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ jobs:
6060
pip install -r build_requirements.txt -r test_requirements.txt
6161
6262
# use meson to build and test
63-
spin build --with-scipy-openblas=64
63+
spin build --with-scipy-openblas=64 -- -Duse-ilp64=true
6464
spin test -j auto
6565
6666
- name: Meson Log

.github/workflows/macos.yml

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ jobs:
100100
ccache -s
101101
102102
accelerate:
103-
name: Accelerate ILP64
103+
name: Accelerate (LP64, ILP64)
104104
if: "github.repository == 'numpy/numpy'"
105105
runs-on: macos-13
106106
steps:
@@ -122,14 +122,15 @@ jobs:
122122
pip install -r build_requirements.txt
123123
pip install pytest pytest-xdist hypothesis
124124
125-
- name: Build NumPy against Accelerate (ILP64)
126-
run: |
127-
spin build -- -Dblas=accelerate -Dlapack=accelerate -Duse-ilp64=true
125+
- name: Build against Accelerate (LP64)
126+
run: spin build -- -Ddisable-optimization=true
128127

129-
- name: Show meson-log.txt
130-
if: always()
131-
run: 'cat build/meson-logs/meson-log.txt'
128+
- name: Test (linalg only)
129+
run: spin test -j2 -- numpy/linalg
132130

133-
- name: Test
131+
- name: Build NumPy against Accelerate (ILP64)
134132
run: |
135-
spin test -j2
133+
spin build -- -Duse-ilp64=true
134+
135+
- name: Test (fast tests)
136+
run: spin test -j2

azure-steps-windows.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ steps:
3131
}
3232
elseif ( Test-Path env:NPY_USE_BLAS_ILP64 ) {
3333
python -m pip install scipy-openblas64 spin
34-
spin config-openblas --with-scipy-openblas=64
34+
spin config-openblas --with-scipy-openblas=64 -- -Duse-ilp64=true
3535
$env:PKG_CONFIG_PATH="$pwd/.openblas"
3636
python -m pip install . -v -Csetup-args="--vsenv"
3737
} else {

meson.build

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,6 @@ project(
1212
'b_ndebug=if-release',
1313
'c_std=c99',
1414
'cpp_std=c++17',
15-
'blas=openblas',
16-
'lapack=openblas',
1715
'pkgconfig.relocatable=true',
1816
],
1917
)

meson_options.txt

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,19 @@
1-
option('blas', type: 'string', value: 'openblas',
2-
description: 'Option for BLAS library switching')
3-
option('lapack', type: 'string', value: 'openblas',
4-
description: 'Option for LAPACK library switching')
1+
option('blas', type: 'string', value: 'auto',
2+
description: 'Option for BLAS library selection. By default, try to find any in the order given by `blas-order`')
3+
option('lapack', type: 'string', value: 'auto',
4+
description: 'Option for LAPACK library selection. By default, try to find any in the order given by `lapack-order`')
55
option('allow-noblas', type: 'boolean', value: false,
66
description: 'If set to true, allow building with (slow!) internal fallback routines')
7+
option('blas-order', type: 'array',
8+
value: ['mkl', 'accelerate', 'openblas', 'flexiblas', 'blis', 'blas'])
9+
option('lapack-order', type: 'array',
10+
value: ['mkl', 'accelerate', 'openblas', 'flexiblas', 'lapack'])
711
option('use-ilp64', type: 'boolean', value: false,
812
description: 'Use ILP64 (64-bit integer) BLAS and LAPACK interfaces')
9-
option('blas-symbol-suffix', type: 'string', value: '',
10-
description: 'BLAS and LAPACK symbol suffix to use, if any (often `64_` for ILP64)')
13+
option('blas-symbol-suffix', type: 'string', value: 'auto',
14+
description: 'BLAS and LAPACK symbol suffix to use, if any')
15+
option('mkl-threading', type: 'string', value: 'auto',
16+
description: 'MKL threading method, one of: `seq`, `iomp`, `gomp`, `tbb`')
1117
option('disable-svml', type: 'boolean', value: false,
1218
description: 'Disable building against SVML')
1319
option('disable-threading', type: 'boolean', value: false,

numpy/core/src/common/npy_cblas.h

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,21 @@ enum CBLAS_SIDE {CblasLeft=141, CblasRight=142};
5757
#define BLAS_FUNC_CONCAT(name,prefix,suffix,suffix2) prefix ## name ## suffix ## suffix2
5858
#define BLAS_FUNC_EXPAND(name,prefix,suffix,suffix2) BLAS_FUNC_CONCAT(name,prefix,suffix,suffix2)
5959

60-
#define CBLAS_FUNC(name) BLAS_FUNC_EXPAND(name,BLAS_SYMBOL_PREFIX,,BLAS_SYMBOL_SUFFIX)
60+
/*
61+
* Use either the OpenBLAS scheme with the `64_` suffix behind the Fortran
62+
* compiler symbol mangling, or the MKL scheme (and upcoming
63+
* reference-lapack#666) which does it the other way around and uses `_64`.
64+
*/
65+
#ifdef OPENBLAS_ILP64_NAMING_SCHEME
6166
#define BLAS_FUNC(name) BLAS_FUNC_EXPAND(name,BLAS_SYMBOL_PREFIX,BLAS_FORTRAN_SUFFIX,BLAS_SYMBOL_SUFFIX)
67+
#else
68+
#define BLAS_FUNC(name) BLAS_FUNC_EXPAND(name,BLAS_SYMBOL_PREFIX,BLAS_SYMBOL_SUFFIX,BLAS_FORTRAN_SUFFIX)
69+
#endif
70+
/*
71+
* Note that CBLAS doesn't include Fortran compiler symbol mangling, so ends up
72+
* being the same in both schemes
73+
*/
74+
#define CBLAS_FUNC(name) BLAS_FUNC_EXPAND(name,BLAS_SYMBOL_PREFIX,,BLAS_SYMBOL_SUFFIX)
6275

6376
#ifdef HAVE_BLAS_ILP64
6477
#define CBLAS_INT npy_int64

0 commit comments

Comments
 (0)
0