numexpr 2.10.2__tar.gz → 2.11.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {numexpr-2.10.2 → numexpr-2.11.0}/ANNOUNCE.rst +16 -11
- {numexpr-2.10.2 → numexpr-2.11.0}/AUTHORS.txt +1 -1
- {numexpr-2.10.2 → numexpr-2.11.0}/PKG-INFO +24 -5
- {numexpr-2.10.2 → numexpr-2.11.0}/README.rst +18 -0
- {numexpr-2.10.2 → numexpr-2.11.0}/RELEASE_NOTES.rst +18 -1
- numexpr-2.11.0/VERSION +1 -0
- {numexpr-2.10.2 → numexpr-2.11.0}/bench/boolean_timing.py +2 -0
- numexpr-2.11.0/bench/free_threading.py +171 -0
- {numexpr-2.10.2 → numexpr-2.11.0}/bench/issue-36.py +6 -3
- {numexpr-2.10.2 → numexpr-2.11.0}/bench/issue-47.py +1 -0
- {numexpr-2.10.2 → numexpr-2.11.0}/bench/large_array_vs_numpy.py +4 -2
- {numexpr-2.10.2 → numexpr-2.11.0}/bench/multidim.py +4 -3
- {numexpr-2.10.2 → numexpr-2.11.0}/bench/poly.py +3 -1
- {numexpr-2.10.2 → numexpr-2.11.0}/bench/timing.py +4 -1
- {numexpr-2.10.2 → numexpr-2.11.0}/bench/unaligned-simple.py +3 -0
- {numexpr-2.10.2 → numexpr-2.11.0}/bench/varying-expr.py +3 -0
- {numexpr-2.10.2 → numexpr-2.11.0}/bench/vml_timing.py +3 -0
- {numexpr-2.10.2 → numexpr-2.11.0}/bench/vml_timing2.py +4 -1
- {numexpr-2.10.2 → numexpr-2.11.0}/bench/vml_timing3.py +3 -1
- {numexpr-2.10.2 → numexpr-2.11.0}/numexpr/__init__.py +10 -10
- {numexpr-2.10.2 → numexpr-2.11.0}/numexpr/cpuinfo.py +5 -3
- {numexpr-2.10.2 → numexpr-2.11.0}/numexpr/expressions.py +3 -2
- {numexpr-2.10.2 → numexpr-2.11.0}/numexpr/interp_body.cpp +4 -4
- {numexpr-2.10.2 → numexpr-2.11.0}/numexpr/interpreter.cpp +10 -8
- {numexpr-2.10.2 → numexpr-2.11.0}/numexpr/interpreter.hpp +1 -1
- {numexpr-2.10.2 → numexpr-2.11.0}/numexpr/module.cpp +8 -2
- {numexpr-2.10.2 → numexpr-2.11.0}/numexpr/module.hpp +2 -2
- {numexpr-2.10.2 → numexpr-2.11.0}/numexpr/necompiler.py +77 -73
- {numexpr-2.10.2 → numexpr-2.11.0}/numexpr/numexpr_config.hpp +1 -1
- {numexpr-2.10.2 → numexpr-2.11.0}/numexpr/numexpr_object.cpp +0 -1
- {numexpr-2.10.2 → numexpr-2.11.0}/numexpr/tests/__init__.py +1 -1
- numexpr-2.11.0/numexpr/tests/conftest.py +16 -0
- {numexpr-2.10.2 → numexpr-2.11.0}/numexpr/tests/test_numexpr.py +156 -127
- {numexpr-2.10.2 → numexpr-2.11.0}/numexpr/utils.py +13 -11
- numexpr-2.11.0/numexpr/version.py +5 -0
- {numexpr-2.10.2 → numexpr-2.11.0}/numexpr/win32/stdint.h +6 -6
- {numexpr-2.10.2 → numexpr-2.11.0}/numexpr.egg-info/PKG-INFO +24 -5
- {numexpr-2.10.2 → numexpr-2.11.0}/numexpr.egg-info/SOURCES.txt +2 -0
- {numexpr-2.10.2 → numexpr-2.11.0}/pyproject.toml +3 -3
- {numexpr-2.10.2 → numexpr-2.11.0}/setup.py +6 -5
- numexpr-2.10.2/VERSION +0 -1
- numexpr-2.10.2/numexpr/version.py +0 -5
- {numexpr-2.10.2 → numexpr-2.11.0}/LICENSE.txt +0 -0
- {numexpr-2.10.2 → numexpr-2.11.0}/MANIFEST.in +0 -0
- {numexpr-2.10.2 → numexpr-2.11.0}/numexpr/complex_functions.hpp +0 -0
- {numexpr-2.10.2 → numexpr-2.11.0}/numexpr/functions.hpp +0 -0
- {numexpr-2.10.2 → numexpr-2.11.0}/numexpr/missing_posix_functions.hpp +0 -0
- {numexpr-2.10.2 → numexpr-2.11.0}/numexpr/msvc_function_stubs.hpp +0 -0
- {numexpr-2.10.2 → numexpr-2.11.0}/numexpr/numexpr_object.hpp +0 -0
- {numexpr-2.10.2 → numexpr-2.11.0}/numexpr/opcodes.hpp +0 -0
- {numexpr-2.10.2 → numexpr-2.11.0}/numexpr/str-two-way.hpp +0 -0
- {numexpr-2.10.2 → numexpr-2.11.0}/numexpr/win32/pthread.c +0 -0
- {numexpr-2.10.2 → numexpr-2.11.0}/numexpr/win32/pthread.h +0 -0
- {numexpr-2.10.2 → numexpr-2.11.0}/numexpr.egg-info/dependency_links.txt +0 -0
- {numexpr-2.10.2 → numexpr-2.11.0}/numexpr.egg-info/requires.txt +0 -0
- {numexpr-2.10.2 → numexpr-2.11.0}/numexpr.egg-info/top_level.txt +0 -0
- {numexpr-2.10.2 → numexpr-2.11.0}/requirements.txt +0 -0
- {numexpr-2.10.2 → numexpr-2.11.0}/setup.cfg +0 -0
- {numexpr-2.10.2 → numexpr-2.11.0}/site.cfg.example +0 -0
|
@@ -1,28 +1,33 @@
|
|
|
1
1
|
=========================
|
|
2
|
-
Announcing NumExpr 2.
|
|
2
|
+
Announcing NumExpr 2.11.0
|
|
3
3
|
=========================
|
|
4
4
|
|
|
5
5
|
Hi everyone,
|
|
6
6
|
|
|
7
|
-
NumExpr 2.
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
the multithreading package in Python.
|
|
7
|
+
NumExpr 2.11.0 Initial support for free-threaded Python 3.13t has been added.
|
|
8
|
+
This is still experimental, so please report any issues you find.
|
|
9
|
+
Finally, Python 3.10 is now the minimum supported version.
|
|
11
10
|
|
|
12
11
|
Project documentation is available at:
|
|
13
12
|
|
|
14
13
|
http://numexpr.readthedocs.io/
|
|
15
14
|
|
|
16
|
-
Changes from 2.10.
|
|
15
|
+
Changes from 2.10.2 to 2.11.0
|
|
17
16
|
-----------------------------
|
|
18
17
|
|
|
19
|
-
*
|
|
20
|
-
|
|
18
|
+
* Initial support for free-threaded Python 3.13t has been added.
|
|
19
|
+
This is still experimental, so please report any issues you find.
|
|
20
|
+
For more info, see discussions PRs #504, #505 and #508.
|
|
21
|
+
Thanks to @andfoy, @rgommers and @FrancescAlted for the work.
|
|
21
22
|
|
|
22
|
-
*
|
|
23
|
-
|
|
23
|
+
* Fix imaginary evaluation in the form of `1.1e1j`. This was
|
|
24
|
+
previously not supported and would raise an error. Thanks to @27rabbitlt
|
|
25
|
+
for the fix.
|
|
24
26
|
|
|
25
|
-
*
|
|
27
|
+
* The test suite has been modernized to use `pytest` instead of `unittest`.
|
|
28
|
+
This should make it easier to run the tests and contribute to the project.
|
|
29
|
+
|
|
30
|
+
* Python 3.10 is now the minimum supported version.
|
|
26
31
|
|
|
27
32
|
What's Numexpr?
|
|
28
33
|
---------------
|
|
@@ -23,7 +23,7 @@ Google Inc. contributed bug fixes.
|
|
|
23
23
|
|
|
24
24
|
David Cox improved readability of the Readme.
|
|
25
25
|
|
|
26
|
-
Robert A. McLeod contributed bug fixes and ported the documentation to
|
|
26
|
+
Robert A. McLeod contributed bug fixes and ported the documentation to
|
|
27
27
|
numexpr.readthedocs.io. He has served as the maintainer of the package
|
|
28
28
|
since 2016 to 2023.
|
|
29
29
|
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: numexpr
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.11.0
|
|
4
4
|
Summary: Fast numerical expression evaluator for NumPy
|
|
5
5
|
Author-email: "David M. Cooke, Francesc Alted, and others" <blosc@blosc.org>
|
|
6
6
|
Maintainer-email: Blosc Development Team <blosc@blosc.org>
|
|
7
|
+
License-Expression: MIT
|
|
7
8
|
Project-URL: homepage, https://github.com/pydata/numexpr
|
|
8
9
|
Project-URL: documentation, https://numexpr.readthedocs.io
|
|
9
10
|
Project-URL: repository, https://github.com/pydata/numexpr
|
|
@@ -11,21 +12,21 @@ Classifier: Development Status :: 6 - Mature
|
|
|
11
12
|
Classifier: Intended Audience :: Developers
|
|
12
13
|
Classifier: Intended Audience :: Information Technology
|
|
13
14
|
Classifier: Intended Audience :: Science/Research
|
|
14
|
-
Classifier: License :: OSI Approved :: MIT License
|
|
15
15
|
Classifier: Programming Language :: Python
|
|
16
16
|
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
17
17
|
Classifier: Operating System :: Microsoft :: Windows
|
|
18
18
|
Classifier: Operating System :: Unix
|
|
19
19
|
Classifier: Programming Language :: Python :: 3
|
|
20
|
-
Classifier: Programming Language :: Python :: 3.9
|
|
21
20
|
Classifier: Programming Language :: Python :: 3.10
|
|
22
21
|
Classifier: Programming Language :: Python :: 3.11
|
|
23
22
|
Classifier: Programming Language :: Python :: 3.12
|
|
24
|
-
|
|
23
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
24
|
+
Requires-Python: >=3.10
|
|
25
25
|
Description-Content-Type: text/x-rst
|
|
26
26
|
License-File: LICENSE.txt
|
|
27
27
|
License-File: AUTHORS.txt
|
|
28
28
|
Requires-Dist: numpy>=1.23.0
|
|
29
|
+
Dynamic: license-file
|
|
29
30
|
|
|
30
31
|
======================================================
|
|
31
32
|
NumExpr: Fast numerical expression evaluator for NumPy
|
|
@@ -188,6 +189,24 @@ Usage
|
|
|
188
189
|
array([ True, False, False], dtype=bool)
|
|
189
190
|
|
|
190
191
|
|
|
192
|
+
Free-threading support
|
|
193
|
+
----------------------
|
|
194
|
+
Starting on CPython 3.13 onwards there is a new distribution that disables the
|
|
195
|
+
Global Interpreter Lock (GIL) altogether, thus increasing the performance yields
|
|
196
|
+
under multi-threaded conditions on a single interpreter, as opposed to having to use
|
|
197
|
+
multiprocessing.
|
|
198
|
+
|
|
199
|
+
Whilst numexpr has been demonstrated to work under free-threaded
|
|
200
|
+
CPython, considerations need to be taken when using numexpr native parallel
|
|
201
|
+
implementation vs using Python threads directly in order to prevent oversubscription,
|
|
202
|
+
we recommend either using the main CPython interpreter thread to spawn multiple C threads
|
|
203
|
+
using the parallel numexpr API, or spawning multiple CPython threads that do not use
|
|
204
|
+
the parallel API.
|
|
205
|
+
|
|
206
|
+
For more information about free-threaded CPython, we recommend visiting the following
|
|
207
|
+
`community Wiki <https://py-free-threading.github.io/>`
|
|
208
|
+
|
|
209
|
+
|
|
191
210
|
Documentation
|
|
192
211
|
-------------
|
|
193
212
|
|
|
@@ -159,6 +159,24 @@ Usage
|
|
|
159
159
|
array([ True, False, False], dtype=bool)
|
|
160
160
|
|
|
161
161
|
|
|
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
|
+
|
|
162
180
|
Documentation
|
|
163
181
|
-------------
|
|
164
182
|
|
|
@@ -1,7 +1,24 @@
|
|
|
1
1
|
=====================================
|
|
2
|
-
Release notes for NumExpr 2.
|
|
2
|
+
Release notes for NumExpr 2.11 series
|
|
3
3
|
=====================================
|
|
4
4
|
|
|
5
|
+
Changes from 2.10.2 to 2.11.0
|
|
6
|
+
-----------------------------
|
|
7
|
+
|
|
8
|
+
* Initial support for free-threaded Python 3.13t has been added.
|
|
9
|
+
This is still experimental, so please report any issues you find.
|
|
10
|
+
For more info, see discussions PRs #504, #505 and #508.
|
|
11
|
+
Thanks to @andfoy, @rgommers and @FrancescAlted for the work.
|
|
12
|
+
|
|
13
|
+
* Fix imaginary evaluation in the form of `1.1e1j`. This was
|
|
14
|
+
previously not supported and would raise an error. Thanks to @27rabbitlt
|
|
15
|
+
for the fix.
|
|
16
|
+
|
|
17
|
+
* The test suite has been modernized to use `pytest` instead of `unittest`.
|
|
18
|
+
This should make it easier to run the tests and contribute to the project.
|
|
19
|
+
|
|
20
|
+
* Python 3.10 is now the minimum supported version.
|
|
21
|
+
|
|
5
22
|
Changes from 2.10.1 to 2.10.2
|
|
6
23
|
-----------------------------
|
|
7
24
|
|
numexpr-2.11.0/VERSION
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
2.11.0
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
#################################################################################
|
|
2
|
+
# To compare the performance of numexpr when free-threading CPython is used.
|
|
3
|
+
#
|
|
4
|
+
# This example makes use of Python threads, as opposed to C native ones
|
|
5
|
+
# in order to highlight the improvement introduced by free-threading CPython,
|
|
6
|
+
# which now disables the GIL altogether.
|
|
7
|
+
#################################################################################
|
|
8
|
+
"""
|
|
9
|
+
Results with GIL-enabled CPython:
|
|
10
|
+
|
|
11
|
+
Benchmarking Expression 1:
|
|
12
|
+
NumPy time (threaded over 32 chunks with 16 threads): 1.173090 seconds
|
|
13
|
+
numexpr time (threaded with re_evaluate over 32 chunks with 16 threads): 0.951071 seconds
|
|
14
|
+
numexpr speedup: 1.23x
|
|
15
|
+
----------------------------------------
|
|
16
|
+
Benchmarking Expression 2:
|
|
17
|
+
NumPy time (threaded over 32 chunks with 16 threads): 10.410874 seconds
|
|
18
|
+
numexpr time (threaded with re_evaluate over 32 chunks with 16 threads): 8.248753 seconds
|
|
19
|
+
numexpr speedup: 1.26x
|
|
20
|
+
----------------------------------------
|
|
21
|
+
Benchmarking Expression 3:
|
|
22
|
+
NumPy time (threaded over 32 chunks with 16 threads): 9.605909 seconds
|
|
23
|
+
numexpr time (threaded with re_evaluate over 32 chunks with 16 threads): 11.087108 seconds
|
|
24
|
+
numexpr speedup: 0.87x
|
|
25
|
+
----------------------------------------
|
|
26
|
+
Benchmarking Expression 4:
|
|
27
|
+
NumPy time (threaded over 32 chunks with 16 threads): 3.836962 seconds
|
|
28
|
+
numexpr time (threaded with re_evaluate over 32 chunks with 16 threads): 18.054531 seconds
|
|
29
|
+
numexpr speedup: 0.21x
|
|
30
|
+
----------------------------------------
|
|
31
|
+
|
|
32
|
+
Results with free-threading CPython:
|
|
33
|
+
|
|
34
|
+
Benchmarking Expression 1:
|
|
35
|
+
NumPy time (threaded over 32 chunks with 16 threads): 3.415349 seconds
|
|
36
|
+
numexpr time (threaded with re_evaluate over 32 chunks with 16 threads): 2.618876 seconds
|
|
37
|
+
numexpr speedup: 1.30x
|
|
38
|
+
----------------------------------------
|
|
39
|
+
Benchmarking Expression 2:
|
|
40
|
+
NumPy time (threaded over 32 chunks with 16 threads): 19.005238 seconds
|
|
41
|
+
numexpr time (threaded with re_evaluate over 32 chunks with 16 threads): 12.611407 seconds
|
|
42
|
+
numexpr speedup: 1.51x
|
|
43
|
+
----------------------------------------
|
|
44
|
+
Benchmarking Expression 3:
|
|
45
|
+
NumPy time (threaded over 32 chunks with 16 threads): 20.555149 seconds
|
|
46
|
+
numexpr time (threaded with re_evaluate over 32 chunks with 16 threads): 17.690749 seconds
|
|
47
|
+
numexpr speedup: 1.16x
|
|
48
|
+
----------------------------------------
|
|
49
|
+
Benchmarking Expression 4:
|
|
50
|
+
NumPy time (threaded over 32 chunks with 16 threads): 38.338372 seconds
|
|
51
|
+
numexpr time (threaded with re_evaluate over 32 chunks with 16 threads): 35.074684 seconds
|
|
52
|
+
numexpr speedup: 1.09x
|
|
53
|
+
----------------------------------------
|
|
54
|
+
"""
|
|
55
|
+
|
|
56
|
+
import os
|
|
57
|
+
|
|
58
|
+
os.environ["NUMEXPR_NUM_THREADS"] = "2"
|
|
59
|
+
import threading
|
|
60
|
+
import timeit
|
|
61
|
+
|
|
62
|
+
import numpy as np
|
|
63
|
+
|
|
64
|
+
import numexpr as ne
|
|
65
|
+
|
|
66
|
+
array_size = 10**8
|
|
67
|
+
num_runs = 10
|
|
68
|
+
num_chunks = 32 # Number of chunks
|
|
69
|
+
num_threads = 16 # Number of threads constrained by how many chunks memory can hold
|
|
70
|
+
|
|
71
|
+
a = np.random.rand(array_size).reshape(10**4, -1)
|
|
72
|
+
b = np.random.rand(array_size).reshape(10**4, -1)
|
|
73
|
+
c = np.random.rand(array_size).reshape(10**4, -1)
|
|
74
|
+
|
|
75
|
+
chunk_size = array_size // num_chunks
|
|
76
|
+
|
|
77
|
+
expressions_numpy = [
|
|
78
|
+
lambda a, b, c: a + b * c,
|
|
79
|
+
lambda a, b, c: a**2 + b**2 - 2 * a * b * np.cos(c),
|
|
80
|
+
lambda a, b, c: np.sin(a) + np.log(b) * np.sqrt(c),
|
|
81
|
+
lambda a, b, c: np.exp(a) + np.tan(b) - np.sinh(c),
|
|
82
|
+
]
|
|
83
|
+
|
|
84
|
+
expressions_numexpr = [
|
|
85
|
+
"a + b * c",
|
|
86
|
+
"a**2 + b**2 - 2 * a * b * cos(c)",
|
|
87
|
+
"sin(a) + log(b) * sqrt(c)",
|
|
88
|
+
"exp(a) + tan(b) - sinh(c)",
|
|
89
|
+
]
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
def benchmark_numpy_chunk(func, a, b, c, results, indices):
|
|
93
|
+
for index in indices:
|
|
94
|
+
start = index * chunk_size
|
|
95
|
+
end = (index + 1) * chunk_size
|
|
96
|
+
time_taken = timeit.timeit(
|
|
97
|
+
lambda: func(a[start:end], b[start:end], c[start:end]), number=num_runs
|
|
98
|
+
)
|
|
99
|
+
results.append(time_taken)
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
def benchmark_numexpr_re_evaluate(expr, a, b, c, results, indices):
|
|
103
|
+
for index in indices:
|
|
104
|
+
start = index * chunk_size
|
|
105
|
+
end = (index + 1) * chunk_size
|
|
106
|
+
# if index == 0:
|
|
107
|
+
# Evaluate the first chunk with evaluate
|
|
108
|
+
time_taken = timeit.timeit(
|
|
109
|
+
lambda: ne.evaluate(
|
|
110
|
+
expr,
|
|
111
|
+
local_dict={
|
|
112
|
+
"a": a[start:end],
|
|
113
|
+
"b": b[start:end],
|
|
114
|
+
"c": c[start:end],
|
|
115
|
+
},
|
|
116
|
+
),
|
|
117
|
+
number=num_runs,
|
|
118
|
+
)
|
|
119
|
+
results.append(time_taken)
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
def run_benchmark_threaded():
|
|
123
|
+
chunk_indices = list(range(num_chunks))
|
|
124
|
+
|
|
125
|
+
for i in range(len(expressions_numpy)):
|
|
126
|
+
print(f"Benchmarking Expression {i+1}:")
|
|
127
|
+
|
|
128
|
+
results_numpy = []
|
|
129
|
+
results_numexpr = []
|
|
130
|
+
|
|
131
|
+
threads_numpy = []
|
|
132
|
+
for j in range(num_threads):
|
|
133
|
+
indices = chunk_indices[j::num_threads] # Distribute chunks across threads
|
|
134
|
+
thread = threading.Thread(
|
|
135
|
+
target=benchmark_numpy_chunk,
|
|
136
|
+
args=(expressions_numpy[i], a, b, c, results_numpy, indices),
|
|
137
|
+
)
|
|
138
|
+
threads_numpy.append(thread)
|
|
139
|
+
thread.start()
|
|
140
|
+
|
|
141
|
+
for thread in threads_numpy:
|
|
142
|
+
thread.join()
|
|
143
|
+
|
|
144
|
+
numpy_time = sum(results_numpy)
|
|
145
|
+
print(
|
|
146
|
+
f"NumPy time (threaded over {num_chunks} chunks with {num_threads} threads): {numpy_time:.6f} seconds"
|
|
147
|
+
)
|
|
148
|
+
|
|
149
|
+
threads_numexpr = []
|
|
150
|
+
for j in range(num_threads):
|
|
151
|
+
indices = chunk_indices[j::num_threads] # Distribute chunks across threads
|
|
152
|
+
thread = threading.Thread(
|
|
153
|
+
target=benchmark_numexpr_re_evaluate,
|
|
154
|
+
args=(expressions_numexpr[i], a, b, c, results_numexpr, indices),
|
|
155
|
+
)
|
|
156
|
+
threads_numexpr.append(thread)
|
|
157
|
+
thread.start()
|
|
158
|
+
|
|
159
|
+
for thread in threads_numexpr:
|
|
160
|
+
thread.join()
|
|
161
|
+
|
|
162
|
+
numexpr_time = sum(results_numexpr)
|
|
163
|
+
print(
|
|
164
|
+
f"numexpr time (threaded with re_evaluate over {num_chunks} chunks with {num_threads} threads): {numexpr_time:.6f} seconds"
|
|
165
|
+
)
|
|
166
|
+
print(f"numexpr speedup: {numpy_time / numexpr_time:.2f}x")
|
|
167
|
+
print("-" * 40)
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
if __name__ == "__main__":
|
|
171
|
+
run_benchmark_threaded()
|
|
@@ -2,10 +2,14 @@
|
|
|
2
2
|
# performs better than the serial code. See issue #36 for details.
|
|
3
3
|
|
|
4
4
|
from __future__ import print_function
|
|
5
|
+
|
|
6
|
+
from time import time
|
|
7
|
+
|
|
5
8
|
import numpy as np
|
|
6
|
-
import numexpr as ne
|
|
7
9
|
from numpy.testing import assert_array_equal
|
|
8
|
-
|
|
10
|
+
|
|
11
|
+
import numexpr as ne
|
|
12
|
+
|
|
9
13
|
|
|
10
14
|
def bench(N):
|
|
11
15
|
print("*** array length:", N)
|
|
@@ -31,4 +35,3 @@ if __name__ == "__main__":
|
|
|
31
35
|
ne.set_num_threads(2)
|
|
32
36
|
for N in range(10, 20):
|
|
33
37
|
bench(2**N)
|
|
34
|
-
|
|
@@ -31,10 +31,12 @@ numexpr speedup: 2.38x
|
|
|
31
31
|
import os
|
|
32
32
|
|
|
33
33
|
os.environ["NUMEXPR_NUM_THREADS"] = "16"
|
|
34
|
+
import threading
|
|
35
|
+
import timeit
|
|
36
|
+
|
|
34
37
|
import numpy as np
|
|
38
|
+
|
|
35
39
|
import numexpr as ne
|
|
36
|
-
import timeit
|
|
37
|
-
import threading
|
|
38
40
|
|
|
39
41
|
array_size = 10**8
|
|
40
42
|
num_runs = 10
|
|
@@ -12,9 +12,12 @@
|
|
|
12
12
|
# Based on a script provided by Andrew Collette.
|
|
13
13
|
|
|
14
14
|
from __future__ import print_function
|
|
15
|
+
|
|
16
|
+
import time
|
|
17
|
+
|
|
15
18
|
import numpy as np
|
|
19
|
+
|
|
16
20
|
import numexpr as nx
|
|
17
|
-
import time
|
|
18
21
|
|
|
19
22
|
test_shapes = [
|
|
20
23
|
(100*100*100),
|
|
@@ -90,5 +93,3 @@ for test_shape in test_shapes:
|
|
|
90
93
|
print("Simple: ", (stop1-start1)/nruns)
|
|
91
94
|
print("Numexpr: ", (stop2-start2)/nruns)
|
|
92
95
|
print("Chunked: ", (stop3-start3)/nruns)
|
|
93
|
-
|
|
94
|
-
|
|
@@ -17,11 +17,13 @@
|
|
|
17
17
|
#######################################################################
|
|
18
18
|
|
|
19
19
|
from __future__ import print_function
|
|
20
|
+
|
|
20
21
|
import sys
|
|
21
22
|
from time import time
|
|
23
|
+
|
|
22
24
|
import numpy as np
|
|
23
|
-
import numexpr as ne
|
|
24
25
|
|
|
26
|
+
import numexpr as ne
|
|
25
27
|
|
|
26
28
|
#expr = ".25*x**3 + .75*x**2 - 1.5*x - 2" # the polynomial to compute
|
|
27
29
|
expr = "((.25*x + .75)*x - 1.5)*x - 2" # a computer-friendly polynomial
|
|
@@ -4,11 +4,14 @@
|
|
|
4
4
|
# https://github.com/pydata/numexpr/wiki/NumexprMKL
|
|
5
5
|
|
|
6
6
|
from __future__ import print_function
|
|
7
|
+
|
|
7
8
|
import datetime
|
|
8
9
|
import sys
|
|
10
|
+
from time import time
|
|
11
|
+
|
|
9
12
|
import numpy as np
|
|
13
|
+
|
|
10
14
|
import numexpr as ne
|
|
11
|
-
from time import time
|
|
12
15
|
|
|
13
16
|
N = int(2**26)
|
|
14
17
|
|
|
@@ -21,21 +21,20 @@ for more info about it.
|
|
|
21
21
|
|
|
22
22
|
"""
|
|
23
23
|
|
|
24
|
-
from numexpr.interpreter import MAX_THREADS, use_vml
|
|
24
|
+
from numexpr.interpreter import __BLOCK_SIZE1__, MAX_THREADS, use_vml
|
|
25
25
|
|
|
26
26
|
is_cpu_amd_intel = False # DEPRECATION WARNING: WILL BE REMOVED IN FUTURE RELEASE
|
|
27
27
|
|
|
28
|
-
# cpuinfo imports were moved into the test submodule function that calls them
|
|
28
|
+
# cpuinfo imports were moved into the test submodule function that calls them
|
|
29
29
|
# to improve import times.
|
|
30
30
|
|
|
31
31
|
from numexpr.expressions import E
|
|
32
|
-
from numexpr.necompiler import (NumExpr, disassemble, evaluate, re_evaluate,
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
detect_number_of_cores, detect_number_of_threads)
|
|
32
|
+
from numexpr.necompiler import (NumExpr, disassemble, evaluate, re_evaluate,
|
|
33
|
+
validate)
|
|
34
|
+
from numexpr.utils import (_init_num_threads, detect_number_of_cores,
|
|
35
|
+
detect_number_of_threads, get_num_threads,
|
|
36
|
+
get_vml_version, set_num_threads,
|
|
37
|
+
set_vml_accuracy_mode, set_vml_num_threads)
|
|
39
38
|
|
|
40
39
|
# Detect the number of cores
|
|
41
40
|
ncores = detect_number_of_cores()
|
|
@@ -45,6 +44,7 @@ nthreads = _init_num_threads()
|
|
|
45
44
|
# set_vml_num_threads(1)
|
|
46
45
|
|
|
47
46
|
from . import version
|
|
47
|
+
|
|
48
48
|
__version__ = version.version
|
|
49
49
|
|
|
50
50
|
def print_versions():
|
|
@@ -63,4 +63,4 @@ def test(verbosity=1):
|
|
|
63
63
|
return numexpr.tests.test(verbosity=verbosity)
|
|
64
64
|
except ImportError:
|
|
65
65
|
# To maintain Python 2.6 compatibility we have simple error handling
|
|
66
|
-
raise ImportError('`numexpr.tests` could not be imported, likely it was excluded from the distribution.')
|
|
66
|
+
raise ImportError('`numexpr.tests` could not be imported, likely it was excluded from the distribution.')
|
|
@@ -23,12 +23,14 @@ Pearu Peterson
|
|
|
23
23
|
|
|
24
24
|
__all__ = ['cpu']
|
|
25
25
|
|
|
26
|
-
import
|
|
26
|
+
import inspect
|
|
27
27
|
import os
|
|
28
|
+
import platform
|
|
29
|
+
import re
|
|
28
30
|
import subprocess
|
|
31
|
+
import sys
|
|
32
|
+
import types
|
|
29
33
|
import warnings
|
|
30
|
-
import platform
|
|
31
|
-
import inspect
|
|
32
34
|
|
|
33
35
|
is_cpu_amd_intel = False # DEPRECATION WARNING: WILL BE REMOVED IN FUTURE RELEASE
|
|
34
36
|
|
|
@@ -35,6 +35,7 @@ scalar_constant_types = tuple(scalar_constant_types)
|
|
|
35
35
|
|
|
36
36
|
from numexpr import interpreter
|
|
37
37
|
|
|
38
|
+
|
|
38
39
|
class Expression():
|
|
39
40
|
|
|
40
41
|
def __getattr__(self, name):
|
|
@@ -269,10 +270,10 @@ def rtruediv_op(a, b):
|
|
|
269
270
|
|
|
270
271
|
@ophelper
|
|
271
272
|
def pow_op(a, b):
|
|
272
|
-
|
|
273
|
+
|
|
273
274
|
if isinstance(b, ConstantNode):
|
|
274
275
|
x = b.value
|
|
275
|
-
if ( a.astKind in ('int', 'long') and
|
|
276
|
+
if ( a.astKind in ('int', 'long') and
|
|
276
277
|
b.astKind in ('int', 'long') and x < 0) :
|
|
277
278
|
raise ValueError(
|
|
278
279
|
'Integers to negative integer powers are not allowed.')
|
|
@@ -7,13 +7,13 @@
|
|
|
7
7
|
See LICENSE.txt for details about copyright and rights to use.
|
|
8
8
|
**********************************************************************/
|
|
9
9
|
|
|
10
|
-
// WARNING: This file is included multiple times in `interpreter.cpp`. It is
|
|
11
|
-
// essentially a very macro-heavy jump table. Interpretation is best done by
|
|
10
|
+
// WARNING: This file is included multiple times in `interpreter.cpp`. It is
|
|
11
|
+
// essentially a very macro-heavy jump table. Interpretation is best done by
|
|
12
12
|
// the developer by expanding all macros (e.g. adding `'-E'` to the `extra_cflags`
|
|
13
13
|
// argument in `setup.py` and looking at the resulting `interpreter.cpp`.
|
|
14
14
|
//
|
|
15
|
-
// Changes made to this file will not be recognized by the compile, so the developer
|
|
16
|
-
// must make a trivial change is made to `interpreter.cpp` or delete the `build/`
|
|
15
|
+
// Changes made to this file will not be recognized by the compile, so the developer
|
|
16
|
+
// must make a trivial change is made to `interpreter.cpp` or delete the `build/`
|
|
17
17
|
// directory in-between each build.
|
|
18
18
|
{
|
|
19
19
|
#define VEC_LOOP(expr) for(j = 0; j < BLOCK_SIZE; j++) { \
|