chore: import upstream snapshot with attribution
Build / Build and test on ubuntu-latest for x86_64 (push) Failing after 1s
Build / Build and test on ubuntu-latest (numpy 1.26) for x86_64 (push) Failing after 0s
Build / Build and test on ubuntu-24.04-arm for aarch64 (push) Has been cancelled
Build / Build and test on windows-11-arm for aarch64 (push) Has been cancelled
Build / Build and test on macos-latest for x86_64 (push) Has been cancelled
Build / Build and test on windows-latest for x86_64 (push) Has been cancelled

This commit is contained in:
wehub-resource-sync
2026-07-13 12:31:22 +08:00
commit 28558dca80
74 changed files with 15578 additions and 0 deletions
+164
View File
@@ -0,0 +1,164 @@
###################################################################
# Numexpr - Fast numerical array expression evaluator for NumPy.
#
# License: MIT
# Author: See AUTHORS.txt
#
# See LICENSE.txt and LICENSES/*.txt for details about copyright and
# rights to use.
####################################################################
from __future__ import print_function
import sys
import timeit
import numpy
array_size = 5_000_000
iterations = 10
numpy_ttime = []
numpy_sttime = []
numpy_nttime = []
numexpr_ttime = []
numexpr_sttime = []
numexpr_nttime = []
def compare_times(expr, nexpr):
global numpy_ttime
global numpy_sttime
global numpy_nttime
global numexpr_ttime
global numexpr_sttime
global numexpr_nttime
print("******************* Expression:", expr)
setup_contiguous = setupNP_contiguous
setup_strided = setupNP_strided
setup_unaligned = setupNP_unaligned
numpy_timer = timeit.Timer(expr, setup_contiguous)
numpy_time = round(numpy_timer.timeit(number=iterations), 4)
numpy_ttime.append(numpy_time)
print('numpy:', numpy_time / iterations)
numpy_timer = timeit.Timer(expr, setup_strided)
numpy_stime = round(numpy_timer.timeit(number=iterations), 4)
numpy_sttime.append(numpy_stime)
print('numpy strided:', numpy_stime / iterations)
numpy_timer = timeit.Timer(expr, setup_unaligned)
numpy_ntime = round(numpy_timer.timeit(number=iterations), 4)
numpy_nttime.append(numpy_ntime)
print('numpy unaligned:', numpy_ntime / iterations)
evalexpr = 'evaluate("%s", optimization="aggressive")' % expr
numexpr_timer = timeit.Timer(evalexpr, setup_contiguous)
numexpr_time = round(numexpr_timer.timeit(number=iterations), 4)
numexpr_ttime.append(numexpr_time)
print("numexpr:", numexpr_time/iterations, end=" ")
print("Speed-up of numexpr over numpy:", round(numpy_time/numexpr_time, 4))
evalexpr = 'evaluate("%s", optimization="aggressive")' % expr
numexpr_timer = timeit.Timer(evalexpr, setup_strided)
numexpr_stime = round(numexpr_timer.timeit(number=iterations), 4)
numexpr_sttime.append(numexpr_stime)
print("numexpr strided:", numexpr_stime/iterations, end=" ")
print("Speed-up of numexpr strided over numpy:",
round(numpy_stime/numexpr_stime, 4))
evalexpr = 'evaluate("%s", optimization="aggressive")' % expr
numexpr_timer = timeit.Timer(evalexpr, setup_unaligned)
numexpr_ntime = round(numexpr_timer.timeit(number=iterations), 4)
numexpr_nttime.append(numexpr_ntime)
print("numexpr unaligned:", numexpr_ntime/iterations, end=" ")
print("Speed-up of numexpr unaligned over numpy:",
round(numpy_ntime/numexpr_ntime, 4))
setupNP = """\
from numpy import arange, where, arctan2, sqrt
from numpy import rec as records
from numexpr import evaluate
# Initialize a recarray of 16 MB in size
r=records.array(None, formats='a%s,i4,f8', shape=%s)
c1 = r.field('f0')%s
i2 = r.field('f1')%s
f3 = r.field('f2')%s
c1[:] = "a"
i2[:] = arange(%s)/1000
f3[:] = i2/2.
"""
setupNP_contiguous = setupNP % (4, array_size,
".copy()", ".copy()", ".copy()",
array_size)
setupNP_strided = setupNP % (4, array_size, "", "", "", array_size)
setupNP_unaligned = setupNP % (1, array_size, "", "", "", array_size)
expressions = []
expressions.append('i2 > 0')
expressions.append('i2 < 0')
expressions.append('i2 < f3')
expressions.append('i2-10 < f3')
expressions.append('i2*f3+f3*f3 > i2')
expressions.append('0.1*i2 > arctan2(i2, f3)')
expressions.append('i2%2 > 3')
expressions.append('i2%10 < 4')
expressions.append('i2**2 + (f3+1)**-2.5 < 3')
expressions.append('(f3+1)**50 > i2')
expressions.append('sqrt(i2**2 + f3**2) > 1')
expressions.append('(i2>2) | ((f3**2>3) & ~(i2*f3<2))')
def compare(expression=None):
if expression:
compare_times(expression, 1)
sys.exit(0)
nexpr = 0
for expr in expressions:
nexpr += 1
compare_times(expr, nexpr)
print()
if __name__ == '__main__':
import numexpr
numexpr.print_versions()
if len(sys.argv) > 1:
expression = sys.argv[1]
print("expression-->", expression)
compare(expression)
else:
compare()
tratios = numpy.array(numpy_ttime) / numpy.array(numexpr_ttime)
stratios = numpy.array(numpy_sttime) / numpy.array(numexpr_sttime)
ntratios = numpy.array(numpy_nttime) / numpy.array(numexpr_nttime)
print("*************** Numexpr vs NumPy speed-ups *******************")
# print "numpy total:", sum(numpy_ttime)/iterations
# print "numpy strided total:", sum(numpy_sttime)/iterations
# print "numpy unaligned total:", sum(numpy_nttime)/iterations
# print "numexpr total:", sum(numexpr_ttime)/iterations
print("Contiguous case:\t %s (mean), %s (min), %s (max)" % \
(round(tratios.mean(), 2),
round(tratios.min(), 2),
round(tratios.max(), 2)))
# print "numexpr strided total:", sum(numexpr_sttime)/iterations
print("Strided case:\t\t %s (mean), %s (min), %s (max)" % \
(round(stratios.mean(), 2),
round(stratios.min(), 2),
round(stratios.max(), 2)))
# print "numexpr unaligned total:", sum(numexpr_nttime)/iterations
print("Unaligned case:\t\t %s (mean), %s (min), %s (max)" % \
(round(ntratios.mean(), 2),
round(ntratios.min(), 2),
round(ntratios.max(), 2)))
+171
View File
@@ -0,0 +1,171 @@
#################################################################################
# To compare the performance of numexpr when free-threading CPython is used.
#
# This example makes use of Python threads, as opposed to C native ones
# in order to highlight the improvement introduced by free-threading CPython,
# which now disables the GIL altogether.
#################################################################################
"""
Results with GIL-enabled CPython:
Benchmarking Expression 1:
NumPy time (threaded over 32 chunks with 16 threads): 1.173090 seconds
numexpr time (threaded with re_evaluate over 32 chunks with 16 threads): 0.951071 seconds
numexpr speedup: 1.23x
----------------------------------------
Benchmarking Expression 2:
NumPy time (threaded over 32 chunks with 16 threads): 10.410874 seconds
numexpr time (threaded with re_evaluate over 32 chunks with 16 threads): 8.248753 seconds
numexpr speedup: 1.26x
----------------------------------------
Benchmarking Expression 3:
NumPy time (threaded over 32 chunks with 16 threads): 9.605909 seconds
numexpr time (threaded with re_evaluate over 32 chunks with 16 threads): 11.087108 seconds
numexpr speedup: 0.87x
----------------------------------------
Benchmarking Expression 4:
NumPy time (threaded over 32 chunks with 16 threads): 3.836962 seconds
numexpr time (threaded with re_evaluate over 32 chunks with 16 threads): 18.054531 seconds
numexpr speedup: 0.21x
----------------------------------------
Results with free-threading CPython:
Benchmarking Expression 1:
NumPy time (threaded over 32 chunks with 16 threads): 3.415349 seconds
numexpr time (threaded with re_evaluate over 32 chunks with 16 threads): 2.618876 seconds
numexpr speedup: 1.30x
----------------------------------------
Benchmarking Expression 2:
NumPy time (threaded over 32 chunks with 16 threads): 19.005238 seconds
numexpr time (threaded with re_evaluate over 32 chunks with 16 threads): 12.611407 seconds
numexpr speedup: 1.51x
----------------------------------------
Benchmarking Expression 3:
NumPy time (threaded over 32 chunks with 16 threads): 20.555149 seconds
numexpr time (threaded with re_evaluate over 32 chunks with 16 threads): 17.690749 seconds
numexpr speedup: 1.16x
----------------------------------------
Benchmarking Expression 4:
NumPy time (threaded over 32 chunks with 16 threads): 38.338372 seconds
numexpr time (threaded with re_evaluate over 32 chunks with 16 threads): 35.074684 seconds
numexpr speedup: 1.09x
----------------------------------------
"""
import os
os.environ["NUMEXPR_NUM_THREADS"] = "2"
import threading
import timeit
import numpy as np
import numexpr as ne
array_size = 10**8
num_runs = 10
num_chunks = 32 # Number of chunks
num_threads = 16 # Number of threads constrained by how many chunks memory can hold
a = np.random.rand(array_size).reshape(10**4, -1)
b = np.random.rand(array_size).reshape(10**4, -1)
c = np.random.rand(array_size).reshape(10**4, -1)
chunk_size = array_size // num_chunks
expressions_numpy = [
lambda a, b, c: a + b * c,
lambda a, b, c: a**2 + b**2 - 2 * a * b * np.cos(c),
lambda a, b, c: np.sin(a) + np.log(b) * np.sqrt(c),
lambda a, b, c: np.exp(a) + np.tan(b) - np.sinh(c),
]
expressions_numexpr = [
"a + b * c",
"a**2 + b**2 - 2 * a * b * cos(c)",
"sin(a) + log(b) * sqrt(c)",
"exp(a) + tan(b) - sinh(c)",
]
def benchmark_numpy_chunk(func, a, b, c, results, indices):
for index in indices:
start = index * chunk_size
end = (index + 1) * chunk_size
time_taken = timeit.timeit(
lambda: func(a[start:end], b[start:end], c[start:end]), number=num_runs
)
results.append(time_taken)
def benchmark_numexpr_re_evaluate(expr, a, b, c, results, indices):
for index in indices:
start = index * chunk_size
end = (index + 1) * chunk_size
# if index == 0:
# Evaluate the first chunk with evaluate
time_taken = timeit.timeit(
lambda: ne.evaluate(
expr,
local_dict={
"a": a[start:end],
"b": b[start:end],
"c": c[start:end],
},
),
number=num_runs,
)
results.append(time_taken)
def run_benchmark_threaded():
chunk_indices = list(range(num_chunks))
for i in range(len(expressions_numpy)):
print(f"Benchmarking Expression {i+1}:")
results_numpy = []
results_numexpr = []
threads_numpy = []
for j in range(num_threads):
indices = chunk_indices[j::num_threads] # Distribute chunks across threads
thread = threading.Thread(
target=benchmark_numpy_chunk,
args=(expressions_numpy[i], a, b, c, results_numpy, indices),
)
threads_numpy.append(thread)
thread.start()
for thread in threads_numpy:
thread.join()
numpy_time = sum(results_numpy)
print(
f"NumPy time (threaded over {num_chunks} chunks with {num_threads} threads): {numpy_time:.6f} seconds"
)
threads_numexpr = []
for j in range(num_threads):
indices = chunk_indices[j::num_threads] # Distribute chunks across threads
thread = threading.Thread(
target=benchmark_numexpr_re_evaluate,
args=(expressions_numexpr[i], a, b, c, results_numexpr, indices),
)
threads_numexpr.append(thread)
thread.start()
for thread in threads_numexpr:
thread.join()
numexpr_time = sum(results_numexpr)
print(
f"numexpr time (threaded with re_evaluate over {num_chunks} chunks with {num_threads} threads): {numexpr_time:.6f} seconds"
)
print(f"numexpr speedup: {numpy_time / numexpr_time:.2f}x")
print("-" * 40)
if __name__ == "__main__":
run_benchmark_threaded()
+37
View File
@@ -0,0 +1,37 @@
# Small benchmark to get the even point where the threading code
# performs better than the serial code. See issue #36 for details.
from __future__ import print_function
from time import time
import numpy as np
from numpy.testing import assert_array_equal
import numexpr as ne
def bench(N):
print("*** array length:", N)
a = np.arange(N)
t0 = time()
ntimes = (1000*2**15) // N
for i in range(ntimes):
ne.evaluate('a>1000')
print("numexpr--> %.3g" % ((time()-t0)/ntimes,))
t0 = time()
for i in range(ntimes):
eval('a>1000')
print("numpy--> %.3g" % ((time()-t0)/ntimes,))
if __name__ == "__main__":
print("****** Testing with 1 thread...")
ne.set_num_threads(1)
for N in range(10, 20):
bench(2**N)
print("****** Testing with 2 threads...")
ne.set_num_threads(2)
for N in range(10, 20):
bench(2**N)
+8
View File
@@ -0,0 +1,8 @@
import numpy
import numexpr
numexpr.set_num_threads(8)
x0,x1,x2,x3,x4,x5 = [0,1,2,3,4,5]
t = numpy.linspace(0,1,44100000).reshape(-1,1)
numexpr.evaluate('(x0+x1*t+x2*t**2)* cos(x3+x4*t+x5**t)')
+154
View File
@@ -0,0 +1,154 @@
#################################################################################
# To mimic the scenario that computation is i/o bound and constrained by memory
#
# It's a much simplified version that the chunk is computed in a loop,
# and expression is evaluated in a sequence, which is not true in reality.
# Neverthless, numexpr outperforms numpy.
#################################################################################
"""
Benchmarking Expression 1:
NumPy time (threaded over 32 chunks with 2 threads): 4.612313 seconds
numexpr time (threaded with re_evaluate over 32 chunks with 2 threads): 0.951172 seconds
numexpr speedup: 4.85x
----------------------------------------
Benchmarking Expression 2:
NumPy time (threaded over 32 chunks with 2 threads): 23.862752 seconds
numexpr time (threaded with re_evaluate over 32 chunks with 2 threads): 2.182058 seconds
numexpr speedup: 10.94x
----------------------------------------
Benchmarking Expression 3:
NumPy time (threaded over 32 chunks with 2 threads): 20.594895 seconds
numexpr time (threaded with re_evaluate over 32 chunks with 2 threads): 2.927881 seconds
numexpr speedup: 7.03x
----------------------------------------
Benchmarking Expression 4:
NumPy time (threaded over 32 chunks with 2 threads): 12.834101 seconds
numexpr time (threaded with re_evaluate over 32 chunks with 2 threads): 5.392480 seconds
numexpr speedup: 2.38x
----------------------------------------
"""
import os
os.environ["NUMEXPR_NUM_THREADS"] = "16"
import threading
import timeit
import numpy as np
import numexpr as ne
array_size = 10**8
num_runs = 10
num_chunks = 32 # Number of chunks
num_threads = 2 # Number of threads constrained by how many chunks memory can hold
a = np.random.rand(array_size).reshape(10**4, -1)
b = np.random.rand(array_size).reshape(10**4, -1)
c = np.random.rand(array_size).reshape(10**4, -1)
chunk_size = array_size // num_chunks
expressions_numpy = [
lambda a, b, c: a + b * c,
lambda a, b, c: a**2 + b**2 - 2 * a * b * np.cos(c),
lambda a, b, c: np.sin(a) + np.log(b) * np.sqrt(c),
lambda a, b, c: np.exp(a) + np.tan(b) - np.sinh(c),
]
expressions_numexpr = [
"a + b * c",
"a**2 + b**2 - 2 * a * b * cos(c)",
"sin(a) + log(b) * sqrt(c)",
"exp(a) + tan(b) - sinh(c)",
]
def benchmark_numpy_chunk(func, a, b, c, results, indices):
for index in indices:
start = index * chunk_size
end = (index + 1) * chunk_size
time_taken = timeit.timeit(
lambda: func(a[start:end], b[start:end], c[start:end]), number=num_runs
)
results.append(time_taken)
def benchmark_numexpr_re_evaluate(expr, a, b, c, results, indices):
for index in indices:
start = index * chunk_size
end = (index + 1) * chunk_size
if index == 0 or index == 1:
# Evaluate the first chunk with evaluate
time_taken = timeit.timeit(
lambda: ne.evaluate(
expr,
local_dict={
"a": a[start:end],
"b": b[start:end],
"c": c[start:end],
},
),
number=num_runs,
)
else:
# Re-evaluate subsequent chunks with re_evaluate
time_taken = timeit.timeit(
lambda: ne.re_evaluate(
local_dict={"a": a[start:end], "b": b[start:end], "c": c[start:end]}
),
number=num_runs,
)
results.append(time_taken)
def run_benchmark_threaded():
chunk_indices = list(range(num_chunks))
for i in range(len(expressions_numpy)):
print(f"Benchmarking Expression {i+1}:")
results_numpy = []
results_numexpr = []
threads_numpy = []
for j in range(num_threads):
indices = chunk_indices[j::num_threads] # Distribute chunks across threads
thread = threading.Thread(
target=benchmark_numpy_chunk,
args=(expressions_numpy[i], a, b, c, results_numpy, indices),
)
threads_numpy.append(thread)
thread.start()
for thread in threads_numpy:
thread.join()
numpy_time = sum(results_numpy)
print(
f"NumPy time (threaded over {num_chunks} chunks with {num_threads} threads): {numpy_time:.6f} seconds"
)
threads_numexpr = []
for j in range(num_threads):
indices = chunk_indices[j::num_threads] # Distribute chunks across threads
thread = threading.Thread(
target=benchmark_numexpr_re_evaluate,
args=(expressions_numexpr[i], a, b, c, results_numexpr, indices),
)
threads_numexpr.append(thread)
thread.start()
for thread in threads_numexpr:
thread.join()
numexpr_time = sum(results_numexpr)
print(
f"numexpr time (threaded with re_evaluate over {num_chunks} chunks with {num_threads} threads): {numexpr_time:.6f} seconds"
)
print(f"numexpr speedup: {numpy_time / numexpr_time:.2f}x")
print("-" * 40)
if __name__ == "__main__":
run_benchmark_threaded()
+95
View File
@@ -0,0 +1,95 @@
###################################################################
# Numexpr - Fast numerical array expression evaluator for NumPy.
#
# License: MIT
# Author: See AUTHORS.txt
#
# See LICENSE.txt and LICENSES/*.txt for details about copyright and
# rights to use.
####################################################################
# Script to check that multidimensional arrays are speed-up properly too
# Based on a script provided by Andrew Collette.
from __future__ import print_function
import time
import numpy as np
import numexpr as nx
test_shapes = [
(100*100*100),
(100*100,100),
(100,100,100),
]
test_dtype = 'f4'
nruns = 10 # Ensemble for timing
def chunkify(chunksize):
""" Very stupid "chunk vectorizer" which keeps memory use down.
This version requires all inputs to have the same number of elements,
although it shouldn't be that hard to implement simple broadcasting.
"""
def chunkifier(func):
def wrap(*args):
assert len(args) > 0
assert all(len(a.flat) == len(args[0].flat) for a in args)
nelements = len(args[0].flat)
nchunks, remain = divmod(nelements, chunksize)
out = np.ndarray(args[0].shape)
for start in range(0, nelements, chunksize):
#print(start)
stop = start+chunksize
if start+chunksize > nelements:
stop = nelements-start
iargs = tuple(a.flat[start:stop] for a in args)
out.flat[start:stop] = func(*iargs)
return out
return wrap
return chunkifier
test_func_str = "63 + (a*b) + (c**2) + b"
def test_func(a, b, c):
return 63 + (a*b) + (c**2) + b
test_func_chunked = chunkify(100*100)(test_func)
for test_shape in test_shapes:
test_size = np.product(test_shape)
# The actual data we'll use
a = np.arange(test_size, dtype=test_dtype).reshape(test_shape)
b = np.arange(test_size, dtype=test_dtype).reshape(test_shape)
c = np.arange(test_size, dtype=test_dtype).reshape(test_shape)
start1 = time.time()
for idx in range(nruns):
result1 = test_func(a, b, c)
stop1 = time.time()
start2 = time.time()
for idx in range(nruns):
result2 = nx.evaluate(test_func_str)
stop2 = time.time()
start3 = time.time()
for idx in range(nruns):
result3 = test_func_chunked(a, b, c)
stop3 = time.time()
print("%s %s (average of %s runs)" % (test_shape, test_dtype, nruns))
print("Simple: ", (stop1-start1)/nruns)
print("Numexpr: ", (stop2-start2)/nruns)
print("Chunked: ", (stop3-start3)/nruns)
+106
View File
@@ -0,0 +1,106 @@
/* ####################################################################### */
/* This script compares the speed of the computation of a polynomial */
/* in C in a couple of different ways. */
/* */
/* Author: Francesc Alted */
/* Date: 2010-02-05 */
/* ####################################################################### */
#include <stdio.h>
#include <math.h>
#if defined(_WIN32) && !defined(__MINGW32__)
#include <time.h>
#include <windows.h>
#else
#include <unistd.h>
#include <sys/time.h>
#endif
#define N 10*1000*1000
double x[N];
double y[N];
#if defined(_WIN32) && !defined(__MINGW32__)
#if defined(_MSC_VER) || defined(_MSC_EXTENSIONS)
#define DELTA_EPOCH_IN_MICROSECS 11644473600000000Ui64
#else
#define DELTA_EPOCH_IN_MICROSECS 11644473600000000ULL
#endif
struct timezone
{
int tz_minuteswest; /* minutes W of Greenwich */
int tz_dsttime; /* type of dst correction */
};
int gettimeofday(struct timeval *tv, struct timezone *tz)
{
FILETIME ft;
unsigned __int64 tmpres = 0;
static int tzflag;
if (NULL != tv)
{
GetSystemTimeAsFileTime(&ft);
tmpres |= ft.dwHighDateTime;
tmpres <<= 32;
tmpres |= ft.dwLowDateTime;
/*converting file time to unix epoch*/
tmpres -= DELTA_EPOCH_IN_MICROSECS;
tmpres /= 10; /*convert into microseconds*/
tv->tv_sec = (long)(tmpres / 1000000UL);
tv->tv_usec = (long)(tmpres % 1000000UL);
}
if (NULL != tz)
{
if (!tzflag)
{
_tzset();
tzflag++;
}
tz->tz_minuteswest = _timezone / 60;
tz->tz_dsttime = _daylight;
}
return 0;
}
#endif /* _WIN32 */
/* Given two timeval stamps, return the difference in seconds */
float getseconds(struct timeval last, struct timeval current) {
int sec, usec;
sec = current.tv_sec - last.tv_sec;
usec = current.tv_usec - last.tv_usec;
return (float)(((double)sec + usec*1e-6));
}
int main(void) {
int i;
double inf = -1;
struct timeval last, current;
float tspend;
for(i=0; i<N; i++) {
x[i] = inf+(2.*i)/N;
}
gettimeofday(&last, NULL);
for(i=0; i<N; i++) {
//y[i] = .25*pow(x[i],3.) + .75*pow(x[i],2.) - 1.5*x[i] - 2;
y[i] = ((.25*x[i] + .75)*x[i] - 1.5)*x[i] - 2;
}
gettimeofday(&current, NULL);
tspend = getseconds(last, current);
printf("Compute time:\t %.3fs\n", tspend);
}
+59
View File
@@ -0,0 +1,59 @@
###################################################################
# Numexpr - Fast numerical array expression evaluator for NumPy.
#
# License: MIT
# Author: See AUTHORS.txt
#
# See LICENSE.txt and LICENSES/*.txt for details about copyright and
# rights to use.
####################################################################
#######################################################################
# This script compares the speed of the computation of a polynomial
# for different (numpy and numexpr) in-memory paradigms.
#
# Author: Francesc Alted
# Date: 2010-07-06
#######################################################################
from __future__ import print_function
import sys
from time import time
import numpy as np
import numexpr as ne
#expr = ".25*x**3 + .75*x**2 - 1.5*x - 2" # the polynomial to compute
expr = "((.25*x + .75)*x - 1.5)*x - 2" # a computer-friendly polynomial
N = 10*1000*1000 # the number of points to compute expression
x = np.linspace(-1, 1, N) # the x in range [-1, 1]
#what = "numpy" # uses numpy for computations
what = "numexpr" # uses numexpr for computations
def compute():
"""Compute the polynomial."""
if what == "numpy":
y = eval(expr)
else:
y = ne.evaluate(expr)
return len(y)
if __name__ == '__main__':
if len(sys.argv) > 1: # first arg is the package to use
what = sys.argv[1]
if len(sys.argv) > 2: # second arg is the number of threads to use
nthreads = int(sys.argv[2])
if "ncores" in dir(ne):
ne.set_num_threads(nthreads)
if what not in ("numpy", "numexpr"):
print("Unrecognized module:", what)
sys.exit(0)
print("Computing: '%s' using %s with %d points" % (expr, what, N))
t0 = time()
result = compute()
ts = round(time() - t0, 3)
print("*** Time elapsed:", ts)
+149
View File
@@ -0,0 +1,149 @@
###################################################################
# Numexpr - Fast numerical array expression evaluator for NumPy.
#
# License: MIT
# Author: See AUTHORS.txt
#
# See LICENSE.txt and LICENSES/*.txt for details about copyright and
# rights to use.
####################################################################
from __future__ import print_function
import timeit
import numpy
array_size = 5e6
iterations = 2
# Choose the type you want to benchmark
#dtype = 'int8'
#dtype = 'int16'
#dtype = 'int32'
#dtype = 'int64'
dtype = 'float32'
#dtype = 'float64'
def compare_times(setup, expr):
print("Expression:", expr)
namespace = {}
exec(setup, namespace)
numpy_timer = timeit.Timer(expr, setup)
numpy_time = numpy_timer.timeit(number=iterations)
print('numpy:', numpy_time / iterations)
try:
weave_timer = timeit.Timer('blitz("result=%s")' % expr, setup)
weave_time = weave_timer.timeit(number=iterations)
print("Weave:", weave_time/iterations)
print("Speed-up of weave over numpy:", round(numpy_time/weave_time, 2))
except:
print("Skipping weave timing")
numexpr_timer = timeit.Timer('evaluate("%s", optimization="aggressive")' % expr, setup)
numexpr_time = numexpr_timer.timeit(number=iterations)
print("numexpr:", numexpr_time/iterations)
tratio = numpy_time/numexpr_time
print("Speed-up of numexpr over numpy:", round(tratio, 2))
return tratio
setup1 = """\
from numpy import arange
try: from scipy.weave import blitz
except: pass
from numexpr import evaluate
result = arange(%f, dtype='%s')
b = arange(%f, dtype='%s')
c = arange(%f, dtype='%s')
d = arange(%f, dtype='%s')
e = arange(%f, dtype='%s')
""" % ((array_size, dtype)*5)
expr1 = 'b*c+d*e'
setup2 = """\
from numpy import arange
try: from scipy.weave import blitz
except: pass
from numexpr import evaluate
a = arange(%f, dtype='%s')
b = arange(%f, dtype='%s')
result = arange(%f, dtype='%s')
""" % ((array_size, dtype)*3)
expr2 = '2*a+3*b'
setup3 = """\
from numpy import arange, sin, cos, sinh
try: from scipy.weave import blitz
except: pass
from numexpr import evaluate
a = arange(2*%f, dtype='%s')[::2]
b = arange(%f, dtype='%s')
result = arange(%f, dtype='%s')
""" % ((array_size, dtype)*3)
expr3 = '2*a + (cos(3)+5)*sinh(cos(b))'
setup4 = """\
from numpy import arange, sin, cos, sinh, arctan2
try: from scipy.weave import blitz
except: pass
from numexpr import evaluate
a = arange(2*%f, dtype='%s')[::2]
b = arange(%f, dtype='%s')
result = arange(%f, dtype='%s')
""" % ((array_size, dtype)*3)
expr4 = '2*a + arctan2(a, b)'
setup5 = """\
from numpy import arange, sin, cos, sinh, arctan2, sqrt, where
try: from scipy.weave import blitz
except: pass
from numexpr import evaluate
a = arange(2*%f, dtype='%s')[::2]
b = arange(%f, dtype='%s')
result = arange(%f, dtype='%s')
""" % ((array_size, dtype)*3)
expr5 = 'where(0.1*a > arctan2(a, b), 2*a, arctan2(a,b))'
expr6 = 'where(a != 0.0, 2, b)'
expr7 = 'where(a-10 != 0.0, a, 2)'
expr8 = 'where(a%2 != 0.0, b+5, 2)'
expr9 = 'where(a%2 != 0.0, 2, b+5)'
expr10 = 'a**2 + (b+1)**-2.5'
expr11 = '(a+1)**50'
expr12 = 'sqrt(a**2 + b**2)'
def compare(check_only=False):
experiments = [(setup1, expr1), (setup2, expr2), (setup3, expr3),
(setup4, expr4), (setup5, expr5), (setup5, expr6),
(setup5, expr7), (setup5, expr8), (setup5, expr9),
(setup5, expr10), (setup5, expr11), (setup5, expr12),
]
total = 0
for params in experiments:
total += compare_times(*params)
print
average = total / len(experiments)
print("Average =", round(average, 2))
return average
if __name__ == '__main__':
import numexpr
print("Numexpr version: ", numexpr.__version__)
averages = []
for i in range(iterations):
averages.append(compare())
print("Averages:", ', '.join("%.2f" % x for x in averages))
+44
View File
@@ -0,0 +1,44 @@
###################################################################
# Numexpr - Fast numerical array expression evaluator for NumPy.
#
# License: MIT
# Author: See AUTHORS.txt
#
# See LICENSE.txt and LICENSES/*.txt for details about copyright and
# rights to use.
####################################################################
"""Very simple test that compares the speed of operating with
aligned vs unaligned arrays.
"""
from __future__ import print_function
from timeit import Timer
import numpy as np
import numexpr as ne
niter = 10
#shape = (1000*10000) # unidimensional test
shape = (1000, 10000) # multidimensional test
print("Numexpr version: ", ne.__version__)
Z_fast = np.zeros(shape, dtype=[('x',np.float64),('y',np.int64)])
Z_slow = np.zeros(shape, dtype=[('y1',np.int8),('x',np.float64),('y2',np.int8,(7,))])
x_fast = Z_fast['x']
t = Timer("x_fast * x_fast", "from __main__ import x_fast")
print("NumPy aligned: \t", round(min(t.repeat(3, niter)), 3), "s")
x_slow = Z_slow['x']
t = Timer("x_slow * x_slow", "from __main__ import x_slow")
print("NumPy unaligned:\t", round(min(t.repeat(3, niter)), 3), "s")
t = Timer("ne.evaluate('x_fast * x_fast')", "from __main__ import ne, x_fast")
print("Numexpr aligned:\t", round(min(t.repeat(3, niter)), 3), "s")
t = Timer("ne.evaluate('x_slow * x_slow')", "from __main__ import ne, x_slow")
print("Numexpr unaligned:\t", round(min(t.repeat(3, niter)), 3), "s")
+57
View File
@@ -0,0 +1,57 @@
###################################################################
# Numexpr - Fast numerical array expression evaluator for NumPy.
#
# License: MIT
# Author: See AUTHORS.txt
#
# See LICENSE.txt and LICENSES/*.txt for details about copyright and
# rights to use.
####################################################################
# Benchmark for checking if numexpr leaks memory when evaluating
# expressions that changes continously. It also serves for computing
# the latency of numexpr when working with small arrays.
from __future__ import print_function
import sys
from time import time
import numpy as np
import numexpr as ne
N = 100
M = 10
def timed_eval(eval_func, expr_func):
t1 = time()
for i in range(N):
r = eval_func(expr_func(i))
if i % 10 == 0:
sys.stdout.write('.')
print(" done in %s seconds" % round(time() - t1, 3))
print("Number of iterations %s. Length of the array: %s " % (N, M))
a = np.arange(M)
# lots of duplicates to collapse
#expr = '+'.join('(a + 1) * %d' % i for i in range(50))
# no duplicate to collapse
expr = '+'.join('(a + %d) * %d' % (i, i) for i in range(50))
def non_cacheable(i):
return expr + '+ %d' % i
def cacheable(i):
return expr + '+ i'
print("* Numexpr with non-cacheable expressions: ", end=" ")
timed_eval(ne.evaluate, non_cacheable)
print("* Numexpr with cacheable expressions: ", end=" ")
timed_eval(ne.evaluate, cacheable)
print("* Numpy with non-cacheable expressions: ", end=" ")
timed_eval(eval, non_cacheable)
print("* Numpy with cacheable expressions: ", end=" ")
timed_eval(eval, cacheable)
+174
View File
@@ -0,0 +1,174 @@
###################################################################
# Numexpr - Fast numerical array expression evaluator for NumPy.
#
# License: MIT
# Author: See AUTHORS.txt
#
# See LICENSE.txt and LICENSES/*.txt for details about copyright and
# rights to use.
####################################################################
from __future__ import print_function
import sys
import timeit
import numpy
import numexpr
array_size = 5_000_000
iterations = 10
numpy_ttime = []
numpy_sttime = []
numpy_nttime = []
numexpr_ttime = []
numexpr_sttime = []
numexpr_nttime = []
def compare_times(expr, nexpr):
global numpy_ttime
global numpy_sttime
global numpy_nttime
global numexpr_ttime
global numexpr_sttime
global numexpr_nttime
print("******************* Expression:", expr)
setup_contiguous = setupNP_contiguous
setup_strided = setupNP_strided
setup_unaligned = setupNP_unaligned
numpy_timer = timeit.Timer(expr, setup_contiguous)
numpy_time = round(numpy_timer.timeit(number=iterations), 4)
numpy_ttime.append(numpy_time)
print('%30s %.4f'%('numpy:', numpy_time / iterations))
numpy_timer = timeit.Timer(expr, setup_strided)
numpy_stime = round(numpy_timer.timeit(number=iterations), 4)
numpy_sttime.append(numpy_stime)
print('%30s %.4f'%('numpy strided:', numpy_stime / iterations))
numpy_timer = timeit.Timer(expr, setup_unaligned)
numpy_ntime = round(numpy_timer.timeit(number=iterations), 4)
numpy_nttime.append(numpy_ntime)
print('%30s %.4f'%('numpy unaligned:', numpy_ntime / iterations))
evalexpr = 'evaluate("%s", optimization="aggressive")' % expr
numexpr_timer = timeit.Timer(evalexpr, setup_contiguous)
numexpr_time = round(numexpr_timer.timeit(number=iterations), 4)
numexpr_ttime.append(numexpr_time)
print('%30s %.4f'%("numexpr:", numexpr_time/iterations,), end=" ")
print("Speed-up of numexpr over numpy:", round(numpy_time/numexpr_time, 4))
evalexpr = 'evaluate("%s", optimization="aggressive")' % expr
numexpr_timer = timeit.Timer(evalexpr, setup_strided)
numexpr_stime = round(numexpr_timer.timeit(number=iterations), 4)
numexpr_sttime.append(numexpr_stime)
print('%30s %.4f'%("numexpr strided:", numexpr_stime/iterations,), end=" ")
print("Speed-up of numexpr over numpy:", \
round(numpy_stime/numexpr_stime, 4))
evalexpr = 'evaluate("%s", optimization="aggressive")' % expr
numexpr_timer = timeit.Timer(evalexpr, setup_unaligned)
numexpr_ntime = round(numexpr_timer.timeit(number=iterations), 4)
numexpr_nttime.append(numexpr_ntime)
print('%30s %.4f'%("numexpr unaligned:", numexpr_ntime/iterations,), end=" ")
print("Speed-up of numexpr over numpy:", \
round(numpy_ntime/numexpr_ntime, 4))
print()
setupNP = """\
from numpy import arange, linspace, arctan2, sqrt, sin, cos, exp, log
from numpy import rec as records
#from numexpr import evaluate
from numexpr import %s
# Initialize a recarray of 16 MB in size
r=records.array(None, formats='a%s,i4,f4,f8', shape=%s)
c1 = r.field('f0')%s
i2 = r.field('f1')%s
f3 = r.field('f2')%s
f4 = r.field('f3')%s
c1[:] = "a"
i2[:] = arange(%s)/1000
f3[:] = linspace(0,1,len(i2))
f4[:] = f3*1.23
"""
eval_method = "evaluate"
setupNP_contiguous = setupNP % ((eval_method, 4, array_size,) + \
(".copy()",)*4 + \
(array_size,))
setupNP_strided = setupNP % (eval_method, 4, array_size,
"", "", "", "", array_size)
setupNP_unaligned = setupNP % (eval_method, 1, array_size,
"", "", "", "", array_size)
expressions = []
expressions.append('i2 > 0')
expressions.append('f3+f4')
expressions.append('f3+i2')
expressions.append('exp(f3)')
expressions.append('log(exp(f3)+1)/f4')
expressions.append('0.1*i2 > arctan2(f3, f4)')
expressions.append('sqrt(f3**2 + f4**2) > 1')
expressions.append('sin(f3)>cos(f4)')
expressions.append('f3**f4')
def compare(expression=False):
if expression:
compare_times(expression, 1)
sys.exit(0)
nexpr = 0
for expr in expressions:
nexpr += 1
compare_times(expr, nexpr)
print()
if __name__ == '__main__':
import numexpr
print("Numexpr version: ", numexpr.__version__)
numpy.seterr(all='ignore')
numexpr.set_vml_accuracy_mode('low')
numexpr.set_vml_num_threads(2)
if len(sys.argv) > 1:
expression = sys.argv[1]
print("expression-->", expression)
compare(expression)
else:
compare()
tratios = numpy.array(numpy_ttime) / numpy.array(numexpr_ttime)
stratios = numpy.array(numpy_sttime) / numpy.array(numexpr_sttime)
ntratios = numpy.array(numpy_nttime) / numpy.array(numexpr_nttime)
print("eval method: %s" % eval_method)
print("*************** Numexpr vs NumPy speed-ups *******************")
# print("numpy total:", sum(numpy_ttime)/iterations)
# print("numpy strided total:", sum(numpy_sttime)/iterations)
# print("numpy unaligned total:", sum(numpy_nttime)/iterations)
# print("numexpr total:", sum(numexpr_ttime)/iterations)
print("Contiguous case:\t %s (mean), %s (min), %s (max)" % \
(round(tratios.mean(), 2),
round(tratios.min(), 2),
round(tratios.max(), 2)))
# print("numexpr strided total:", sum(numexpr_sttime)/iterations)
print("Strided case:\t\t %s (mean), %s (min), %s (max)" % \
(round(stratios.mean(), 2),
round(stratios.min(), 2),
round(stratios.max(), 2)))
# print("numexpr unaligned total:", sum(numexpr_nttime)/iterations)
print("Unaligned case:\t\t %s (mean), %s (min), %s (max)" % \
(round(ntratios.mean(), 2),
round(ntratios.min(), 2),
round(ntratios.max(), 2)))
+57
View File
@@ -0,0 +1,57 @@
# References:
#
# http://software.intel.com/en-us/intel-mkl
# https://github.com/pydata/numexpr/wiki/NumexprMKL
from __future__ import print_function
import datetime
import sys
from time import time
import numpy as np
import numexpr as ne
N = int(2**28)
x = np.linspace(0, 1, N)
y = np.linspace(0, 1, N)
z = np.empty(N, dtype=np.float64)
# Our working set is 3 vectors of N doubles each
working_set_GB = 3 * N * 8 / 2**30
print("NumPy version: %s" % (np.__version__,))
t0 = time()
z = 2*y + 4*x
t1 = time()
gbs = working_set_GB / (t1-t0)
print("Time for an algebraic expression: %.3f s / %.3f GB/s" % (t1-t0, gbs))
t0 = time()
z = np.sin(x)**3.2 + np.cos(y)**3.2
t1 = time()
gbs = working_set_GB / (t1-t0)
print("Time for a transcendental expression: %.3f s / %.3f GB/s" % (t1-t0, gbs))
if ne.use_vml:
ne.set_vml_num_threads(1)
ne.set_num_threads(16)
print("NumExpr version: %s, Using MKL ver. %s, Num threads: %s" % (ne.__version__, ne.get_vml_version(), ne.nthreads))
else:
ne.set_num_threads(16)
print("NumExpr version: %s, Not Using MKL, Num threads: %s" % (ne.__version__, ne.nthreads))
t0 = time()
ne.evaluate('2*y + 4*x', out = z)
t1 = time()
gbs = working_set_GB / (t1-t0)
print("Time for an algebraic expression: %.3f s / %.3f GB/s" % (t1-t0, gbs))
t0 = time()
ne.evaluate('sin(x)**3.2 + cos(y)**3.2', out = z)
t1 = time()
gbs = working_set_GB / (t1-t0)
print("Time for a transcendental expression: %.3f s / %.3f GB/s" % (t1-t0, gbs))
+15
View File
@@ -0,0 +1,15 @@
# -*- coding: utf-8 -*-
from timeit import default_timer as timer
import numpy as np
import numexpr as ne
x = np.ones(100000)
scaler = -1J
start = timer()
for k in range(10000):
cexp = ne.evaluate('exp(scaler * x)')
exec_time=(timer() - start)
print("Execution took", str(round(exec_time, 3)), "seconds")