Skip to content

Commit be153c6

Browse files
Merge pull request #505 from pydata/andfoy-support_free_threading
This is an extension of #504 to fix some issues with tests. The tests for aarch64 are currently commented out, because CI (via qemu) gets stalled. However, my arm64 box (MacMini M4) does not have a single issue, so I suppose it is an issue with qemu. This overrides #504. @andfoy @rgommers
2 parents 36aa11b + 0c42b7d commit be153c6

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+489
-337
lines changed

.github/workflows/build.yml

Lines changed: 47 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -6,37 +6,56 @@ permissions:
66
contents: read
77

88
env:
9-
CIBW_BEFORE_BUILD: pip install setuptools oldest-supported-numpy
9+
CIBW_BEFORE_BUILD: pip install setuptools oldest-supported-numpy pytest
10+
CIBW_BEFORE_TEST: pip install pytest
1011
CIBW_BUILD_VERBOSITY: 1
11-
CIBW_TEST_COMMAND: python -c "import sys, numexpr; sys.exit(0 if numexpr.test().wasSuccessful() else 1)"
12-
CIBW_TEST_SKIP: "*macosx*arm64*"
12+
CIBW_TEST_COMMAND: pytest --pyargs numexpr
13+
# Testing on aarch64 takes too long, as it is currently emulated on GitHub Actions
14+
CIBW_TEST_SKIP: "*linux*aarch64*"
1315
# Building for musllinux and aarch64 takes way too much time.
1416
# Moreover, NumPy is not providing musllinux for x86_64 either, so it's not worth it.
1517
CIBW_SKIP: "*musllinux*aarch64* *musllinux*x86_64*"
1618

1719
jobs:
1820
build_wheels:
19-
name: Build wheels on ${{ matrix.os }} for ${{ matrix.arch }} - ${{ matrix.p_ver }}
20-
runs-on: ${{ matrix.os }}
21+
name: Build wheels on ${{ matrix.os }} for ${{ matrix.arch }}
22+
runs-on: ${{ matrix.runs-on || matrix.os }}
2123
permissions:
2224
contents: write
2325
env:
24-
CIBW_BUILD: ${{ matrix.cibw_build }}
26+
CIBW_BUILD: ${{ matrix.cibw_pattern }}
2527
CIBW_ARCHS_LINUX: ${{ matrix.arch }}
2628
CIBW_ARCHS_MACOS: "x86_64 arm64"
29+
CIBW_ENABLE: cpython-freethreading
2730
strategy:
31+
fail-fast: false
2832
matrix:
29-
os: [ubuntu-latest, windows-latest, macos-latest]
30-
arch: [x86_64, aarch64]
31-
cibw_build: ["cp3{10,11,12,13}-*"]
32-
p_ver: ["3.10-3.13"]
33-
exclude:
34-
- os: windows-latest
35-
arch: aarch64
36-
# cibuild is already in charge to build aarch64 (see CIBW_ARCHS_MACOS)
37-
- os: macos-latest
33+
include:
34+
# Linux x86_64 builds
35+
- os: ubuntu-latest
36+
arch: x86_64
37+
cibw_pattern: "cp3{10,11,12,13,13t}-manylinux*"
38+
artifact_name: "linux-x86_64"
39+
40+
# Linux ARM64 builds (native runners)
41+
- os: ubuntu-latest
3842
arch: aarch64
43+
cibw_pattern: "cp3{10,11,12,13,13t}-manylinux*"
44+
artifact_name: "linux-aarch64"
45+
# Don't use native runners for now (looks like wait times are too long)
46+
#runs-on: ["ubuntu-latest", "arm64"]
3947

48+
# Windows builds
49+
- os: windows-latest
50+
arch: x86_64
51+
cibw_pattern: "cp3{10,11,12,13,13t}-win*"
52+
artifact_name: "windows-x86_64"
53+
54+
# macOS builds (universal2)
55+
- os: macos-latest
56+
arch: x86_64
57+
cibw_pattern: "cp3{10,11,12,13,13t}-macosx*"
58+
artifact_name: "macos-universal2"
4059
steps:
4160
- uses: actions/checkout@v3
4261

@@ -45,17 +64,22 @@ jobs:
4564
with:
4665
python-version: '3.x'
4766

48-
- name: Install cibuildwheel
67+
- name: Setup free-threading variables
68+
if: ${{ endsWith(matrix.cibw_build, 't-*') }}
69+
shell: bash -l {0}
4970
run: |
50-
python -m pip install cibuildwheel
71+
echo "CIBW_BEFORE_BUILD=pip install setuptools numpy" >> "$GITHUB_ENV"
72+
echo "CIBW_BEFORE_TEST=pip install pytest pytest-run-parallel" >> "$GITHUB_ENV"
73+
echo "CIBW_TEST_COMMAND=pytest --parallel-threads=4 --pyargs numexpr" >> "$GITHUB_ENV"
5174
52-
- uses: docker/setup-qemu-action@v2
53-
if: ${{ matrix.arch == 'aarch64' }}
54-
name: Set up QEMU
75+
- name: Set up QEMU
76+
if: matrix.arch == 'aarch64'
77+
uses: docker/setup-qemu-action@v3
78+
with:
79+
platforms: arm64
5580

5681
- name: Build wheels
57-
run: |
58-
python -m cibuildwheel --output-dir wheelhouse
82+
uses: pypa/[email protected]
5983

6084
- name: Make sdist
6185
if: ${{ matrix.os == 'windows-latest' }}
@@ -65,6 +89,7 @@ jobs:
6589
6690
- uses: actions/upload-artifact@v4
6791
with:
92+
name: ${{ matrix.artifact_name }}
6893
path: ./wheelhouse/*
6994

7095
- name: Upload to GitHub Release

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ artifact/
77
numexpr.egg-info/
88
*.pyc
99
*.swp
10+
*.so
1011
*~
1112
doc/_build
1213
site.cfg

.pre-commit-config.yaml

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
repos:
2+
- repo: https://github.com/pre-commit/pre-commit-hooks
3+
rev: v4.5.0
4+
hooks:
5+
- id: trailing-whitespace
6+
- id: end-of-file-fixer
7+
- id: check-yaml
8+
- id: debug-statements
9+
10+
# Too many things to fix, let's just ignore it for now
11+
#- repo: https://github.com/pycqa/flake8
12+
# rev: 7.0.0
13+
# hooks:
14+
# - id: flake8
15+
#
16+
- repo: https://github.com/pycqa/isort
17+
rev: 5.13.2
18+
hooks:
19+
- id: isort
20+
21+
# Too many things to fix, let's just ignore it for now
22+
#- repo: https://github.com/pre-commit/mirrors-mypy
23+
# rev: v1.8.0
24+
# hooks:
25+
# - id: mypy
26+
# exclude: ^(docs/|setup.py)

.readthedocs.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,4 +19,4 @@ sphinx:
1919
# https://docs.readthedocs.io/en/stable/guides/reproducible-builds.html
2020
python:
2121
install:
22-
- requirements: doc/requirements.txt
22+
- requirements: doc/requirements.txt

AUTHORS.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ Google Inc. contributed bug fixes.
2323

2424
David Cox improved readability of the Readme.
2525

26-
Robert A. McLeod contributed bug fixes and ported the documentation to
26+
Robert A. McLeod contributed bug fixes and ported the documentation to
2727
numexpr.readthedocs.io. He has served as the maintainer of the package
2828
since 2016 to 2023.
2929

README.rst

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,24 @@ Usage
159159
array([ True, False, False], dtype=bool)
160160

161161

162+
Free-threading support
163+
----------------------
164+
Starting on CPython 3.13 onwards there is a new distribution that disables the
165+
Global Interpreter Lock (GIL) altogether, thus increasing the performance yields
166+
under multi-threaded conditions on a single interpreter, as opposed to having to use
167+
multiprocessing.
168+
169+
Whilst numexpr has been demonstrated to work under free-threaded
170+
CPython, considerations need to be taken when using numexpr native parallel
171+
implementation vs using Python threads directly in order to prevent oversubscription,
172+
we recommend either using the main CPython interpreter thread to spawn multiple C threads
173+
using the parallel numexpr API, or spawning multiple CPython threads that do not use
174+
the parallel API.
175+
176+
For more information about free-threaded CPython, we recommend visiting the following
177+
`community Wiki <https://py-free-threading.github.io/>`
178+
179+
162180
Documentation
163181
-------------
164182

bench/boolean_timing.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,10 @@
99
####################################################################
1010

1111
from __future__ import print_function
12+
1213
import sys
1314
import timeit
15+
1416
import numpy
1517

1618
array_size = 5_000_000

bench/issue-36.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,14 @@
22
# performs better than the serial code. See issue #36 for details.
33

44
from __future__ import print_function
5+
6+
from time import time
7+
58
import numpy as np
6-
import numexpr as ne
79
from numpy.testing import assert_array_equal
8-
from time import time
10+
11+
import numexpr as ne
12+
913

1014
def bench(N):
1115
print("*** array length:", N)
@@ -31,4 +35,3 @@ def bench(N):
3135
ne.set_num_threads(2)
3236
for N in range(10, 20):
3337
bench(2**N)
34-

bench/issue-47.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import numpy
2+
23
import numexpr
34

45
numexpr.set_num_threads(8)

bench/large_array_vs_numpy.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,12 @@
3131
import os
3232

3333
os.environ["NUMEXPR_NUM_THREADS"] = "16"
34+
import threading
35+
import timeit
36+
3437
import numpy as np
38+
3539
import numexpr as ne
36-
import timeit
37-
import threading
3840

3941
array_size = 10**8
4042
num_runs = 10

bench/multidim.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,12 @@
1212
# Based on a script provided by Andrew Collette.
1313

1414
from __future__ import print_function
15+
16+
import time
17+
1518
import numpy as np
19+
1620
import numexpr as nx
17-
import time
1821

1922
test_shapes = [
2023
(100*100*100),
@@ -90,5 +93,3 @@ def test_func(a, b, c):
9093
print("Simple: ", (stop1-start1)/nruns)
9194
print("Numexpr: ", (stop2-start2)/nruns)
9295
print("Chunked: ", (stop3-start3)/nruns)
93-
94-

bench/poly.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,13 @@
1717
#######################################################################
1818

1919
from __future__ import print_function
20+
2021
import sys
2122
from time import time
23+
2224
import numpy as np
23-
import numexpr as ne
2425

26+
import numexpr as ne
2527

2628
#expr = ".25*x**3 + .75*x**2 - 1.5*x - 2" # the polynomial to compute
2729
expr = "((.25*x + .75)*x - 1.5)*x - 2" # a computer-friendly polynomial

bench/timing.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,10 @@
99
####################################################################
1010

1111
from __future__ import print_function
12-
import timeit, numpy
12+
13+
import timeit
14+
15+
import numpy
1316

1417
array_size = 5e6
1518
iterations = 2

bench/unaligned-simple.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,11 @@
1313
"""
1414

1515
from __future__ import print_function
16+
1617
from timeit import Timer
18+
1719
import numpy as np
20+
1821
import numexpr as ne
1922

2023
niter = 10

bench/varying-expr.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,12 @@
1313
# the latency of numexpr when working with small arrays.
1414

1515
from __future__ import print_function
16+
1617
import sys
1718
from time import time
19+
1820
import numpy as np
21+
1922
import numexpr as ne
2023

2124
N = 100

bench/vml_timing.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,12 @@
99
####################################################################
1010

1111
from __future__ import print_function
12+
1213
import sys
1314
import timeit
15+
1416
import numpy
17+
1518
import numexpr
1619

1720
array_size = 5_000_000

bench/vml_timing2.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,14 @@
44
# https://github.com/pydata/numexpr/wiki/NumexprMKL
55

66
from __future__ import print_function
7+
78
import datetime
89
import sys
10+
from time import time
11+
912
import numpy as np
13+
1014
import numexpr as ne
11-
from time import time
1215

1316
N = int(2**26)
1417

bench/vml_timing3.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
# -*- coding: utf-8 -*-
2+
from timeit import default_timer as timer
3+
24
import numpy as np
5+
36
import numexpr as ne
4-
from timeit import default_timer as timer
57

68
x = np.ones(100000)
79
scaler = -1J

doc/api.rst

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,11 @@ NumExpr API
33

44
.. automodule:: numexpr
55
:members: evaluate, re_evaluate, disassemble, NumExpr, get_vml_version, set_vml_accuracy_mode, set_vml_num_threads, set_num_threads, detect_number_of_cores, detect_number_of_threads
6-
6+
77
.. py:attribute:: ncores
88
99
The number of (virtual) cores detected.
10-
10+
1111
.. py:attribute:: nthreads
1212
1313
The number of threads currently in-use.
@@ -18,11 +18,11 @@ NumExpr API
1818

1919
.. py:attribute:: version
2020
21-
The version of NumExpr.
22-
23-
21+
The version of NumExpr.
22+
23+
2424
Tests submodule
2525
---------------
2626

2727
.. automodule:: numexpr.tests
28-
:members: test, print_versions
28+
:members: test, print_versions

doc/index.rst

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,4 +25,3 @@ Indices and tables
2525
* :ref:`genindex`
2626
* :ref:`modindex`
2727
* :ref:`search`
28-

0 commit comments

Comments
 (0)