Skip to content

Commit 33c297d

Browse files
committed
Merged branch multithreaded into trunk.
1 parent c655447 commit 33c297d

12 files changed

+969
-83
lines changed

README.txt

+12-5
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,14 @@ General routines
147147

148148
* test(): Run all the tests in the test suite.
149149

150-
* print_versions(): Print the versions of software that numexpr relies on.
150+
* print_versions(): Print the versions of software that numexpr
151+
relies on.
152+
153+
* set_num_threads(nthreads): Suggests a maximum number of threads to
154+
be used in operations.
155+
156+
* detect_number_of_cores(): Detects the number of cores on a system.
157+
151158

152159

153160
Intel's VML specific support routines
@@ -231,10 +238,10 @@ Authors
231238

232239
Numexpr was initially written by David Cooke, and extended to more
233240
types by Tim Hochberg. Francesc Alted contributed support for
234-
booleans and simple-precision floating point types and for efficient
235-
strided and unaligned array operations. Ivan Vilata contributed
236-
support for strings. Gregor Thalhammer implemented the support for
237-
Intel VML (Vector Math Library).
241+
booleans and simple-precision floating point types, efficient strided
242+
and unaligned array operations and multi-threading code. Ivan Vilata
243+
contributed support for strings. Gregor Thalhammer implemented the
244+
support for Intel VML (Vector Math Library).
238245

239246

240247
License

RELEASE_NOTES.txt

+4
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@
55
Changes from 1.3.1 to development
66
=================================
77

8+
- Added support for multi-threading in pure C. This is to avoid the
9+
GIL and allows to squeeze the best performance in both multi-core
10+
machines.
11+
812
- Fix negation of `int64` numbers. Closes #25.
913

1014
- Using a `npy_intp` datatype (instead of plain `int`) so as to be

bench/poly.c

+106
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
/* ####################################################################### */
2+
/* This script compares the speed of the computation of a polynomial */
3+
/* in C in a couple of different ways. */
4+
/* */
5+
/* Author: Francesc Alted */
6+
/* Date: 2010-02-05 */
7+
/* ####################################################################### */
8+
9+
10+
#include <stdio.h>
11+
#include <math.h>
12+
#if defined(_WIN32) && !defined(__MINGW32__)
13+
#include <time.h>
14+
#include <windows.h>
15+
#else
16+
#include <unistd.h>
17+
#include <sys/time.h>
18+
#endif
19+
20+
21+
#define N 10*1000*1000
22+
23+
double x[N];
24+
double y[N];
25+
26+
27+
#if defined(_WIN32) && !defined(__MINGW32__)
28+
29+
#if defined(_MSC_VER) || defined(_MSC_EXTENSIONS)
30+
#define DELTA_EPOCH_IN_MICROSECS 11644473600000000Ui64
31+
#else
32+
#define DELTA_EPOCH_IN_MICROSECS 11644473600000000ULL
33+
#endif
34+
35+
struct timezone
36+
{
37+
int tz_minuteswest; /* minutes W of Greenwich */
38+
int tz_dsttime; /* type of dst correction */
39+
};
40+
41+
int gettimeofday(struct timeval *tv, struct timezone *tz)
42+
{
43+
FILETIME ft;
44+
unsigned __int64 tmpres = 0;
45+
static int tzflag;
46+
47+
if (NULL != tv)
48+
{
49+
GetSystemTimeAsFileTime(&ft);
50+
51+
tmpres |= ft.dwHighDateTime;
52+
tmpres <<= 32;
53+
tmpres |= ft.dwLowDateTime;
54+
55+
/*converting file time to unix epoch*/
56+
tmpres -= DELTA_EPOCH_IN_MICROSECS;
57+
tmpres /= 10; /*convert into microseconds*/
58+
tv->tv_sec = (long)(tmpres / 1000000UL);
59+
tv->tv_usec = (long)(tmpres % 1000000UL);
60+
}
61+
62+
if (NULL != tz)
63+
{
64+
if (!tzflag)
65+
{
66+
_tzset();
67+
tzflag++;
68+
}
69+
tz->tz_minuteswest = _timezone / 60;
70+
tz->tz_dsttime = _daylight;
71+
}
72+
73+
return 0;
74+
}
75+
#endif /* _WIN32 */
76+
77+
78+
/* Given two timeval stamps, return the difference in seconds */
79+
float getseconds(struct timeval last, struct timeval current) {
80+
int sec, usec;
81+
82+
sec = current.tv_sec - last.tv_sec;
83+
usec = current.tv_usec - last.tv_usec;
84+
return (float)(((double)sec + usec*1e-6));
85+
}
86+
87+
int main(void) {
88+
int i;
89+
double inf = -1;
90+
struct timeval last, current;
91+
float tspend;
92+
93+
for(i=0; i<N; i++) {
94+
x[i] = inf+(2.*i)/N;
95+
}
96+
97+
gettimeofday(&last, NULL);
98+
for(i=0; i<N; i++) {
99+
//y[i] = .25*pow(x[i],3.) + .75*pow(x[i],2.) - 1.5*x[i] - 2;
100+
y[i] = ((.25*x[i] + .75)*x[i] - 1.5)*x[i] - 2;
101+
}
102+
gettimeofday(&current, NULL);
103+
tspend = getseconds(last, current);
104+
printf("Compute time:\t %.3fs\n", tspend);
105+
106+
}

bench/poly.py

+46
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
#######################################################################
2+
# This script compares the speed of the computation of a polynomial
3+
# for different (numpy and numexpr) in-memory paradigms.
4+
#
5+
# Author: Francesc Alted
6+
# Date: 2010-07-06
7+
#######################################################################
8+
9+
import sys
10+
from time import time
11+
import numpy as np
12+
import numexpr as ne
13+
14+
15+
expr = ".25*x**3 + .75*x**2 - 1.5*x - 2" # the polynomial to compute
16+
expr = "((.25*x + .75)*x - 1.5)*x - 2" # a computer-friendly polynomial
17+
N = 10*1000*1000 # the number of points to compute expression
18+
x = np.linspace(-1, 1, N) # the x in range [-1, 1]
19+
20+
#what = "numpy" # uses numpy for computations
21+
what = "numexpr" # uses numexpr for computations
22+
23+
def compute():
24+
"""Compute the polynomial."""
25+
if what == "numpy":
26+
y = eval(expr)
27+
else:
28+
y = ne.evaluate(expr)
29+
return len(y)
30+
31+
32+
if __name__ == '__main__':
33+
if len(sys.argv) > 1: # first arg is the package to use
34+
what = sys.argv[1]
35+
if len(sys.argv) > 2: # second arg is the number of threads to use
36+
nthreads = int(sys.argv[2])
37+
if "ncores" in dir(ne):
38+
ne.set_num_threads(nthreads)
39+
if what not in ("numpy", "numexpr"):
40+
print "Unrecognized module:", what
41+
sys.exit(0)
42+
print "Computing: '%s' using %s with %d points" % (expr, what, N)
43+
t0 = time()
44+
result = compute()
45+
ts = round(time() - t0, 3)
46+
print "*** Time elapsed:", ts

numexpr/__init__.py

+5-2
Original file line numberDiff line numberDiff line change
@@ -29,13 +29,16 @@
2929
from numexpr.necompiler import NumExpr, disassemble, evaluate
3030
from numexpr.tests import test, print_versions
3131
from numexpr.utils import (
32-
get_vml_version, set_vml_accuracy_mode, set_vml_num_threads)
32+
get_vml_version, set_vml_accuracy_mode, set_vml_num_threads,
33+
set_num_threads, detect_number_of_cores)
3334

35+
# Initialize the number of threads to be used
36+
ncores = detect_number_of_cores()
37+
set_num_threads(ncores)
3438

3539
import version
3640

3741
dirname = os.path.dirname(__file__)
3842

3943
__version__ = version.version
4044

41-

0 commit comments

Comments
 (0)