In [1]:
import hope
hope.config.optimize = True
hope.config.verbose = True
hope.config.keeptemp = True
import numba
import numpy as np
import numexpr as ne

from util import perf_comp_data
from native_util import load
%load_ext cythonmagic
%load_ext version_information
%version_information numpy, Cython, numba, hope, numexpr


Out[1]:
SoftwareVersion
Python2.7.8 (default, Jul 13 2014, 17:11:32) [GCC 4.2.1 Compatible Apple LLVM 5.1 (clang-503.0.40)]
IPython1.1.0
OSposix [darwin]
numpy1.8.1
Cython0.20.2
numba0.13.3
hope0.3.0
numexpr2.4
Thu Sep 04 15:17:12 2014 CEST

In [2]:
def poly(res, arg):
    res[:] = np.sin(arg)**2 + (arg**3 + arg**2 - arg - 1)/(arg**2 + 2*arg + 1) + np.cos(arg)**2
hope_poly = hope.jit(poly)
numba_poly = numba.jit(poly, nopython=False)

native_poly_mod = load("poly")
native_poly = native_poly_mod.run


running build_ext
building 'poly' extension
C compiler: /usr/bin/clang -fno-strict-aliasing -fno-common -dynamic -pipe -Os -fwrapv -DNDEBUG -g -fwrapv -O3 -Wall -Wstrict-prototypes

compile options: '-I/Users/jakeret/Library/Python/2.7/lib/python/site-packages/numpy/core/include -I/opt/local/Library/Frameworks/Python.framework/Versions/2.7/include/python2.7 -c'
extra options: '-Wall -Wno-unused-variable -march=native -stdlib=libc++ -std=c++11'
clang: ././src/poly.cpp
/usr/bin/clang++ -bundle -undefined dynamic_lookup -L/opt/local/lib -Wl,-headerpad_max_install_names -L/opt/local/lib/db46 ./src/poly.o -o ./poly.so


In [3]:
%%cython

cimport cython
from libc.math cimport sin
from libc.math cimport cos
from libc.math cimport pow

@cython.boundscheck(False)
@cython.wraparound(False)
def cython_poly(double[:] res, double[:] arg):
    for i in range(len(arg)):
        i_arg = arg[i]
        res[i] = pow(sin(i_arg),2) + (pow(i_arg,3) + pow(i_arg,2) - i_arg - 1)/(pow(i_arg,2) + 2*i_arg + 1) + pow(cos(i_arg),2)

In [4]:
%%cython
cimport cython
import numpy as np
cimport numpy as np

@cython.boundscheck(False)
@cython.wraparound(False)
def cython_numpy_poly(np.ndarray[np.double_t, ndim=1] res, np.ndarray[np.double_t, ndim=1] arg):
    res[:] = np.sin(arg)**2 + (arg**3 + arg**2 - arg - 1)/(arg**2 + 2*arg + 1) + np.cos(arg)**2

In [5]:
# NumExpr version

import numexpr as ne

def numexpr_poly(res, arg):
    res[:] = ne.evaluate("sin(arg)**2 + (arg**3 + arg**2 - arg - 1)/(arg**2 + 2*arg + 1) + cos(arg)**2")

In [7]:
arg = np.random.random(50000)
res = np.empty_like(arg)

res1 = np.empty_like(arg)
res2 = np.empty_like(arg)
res3 = np.empty_like(arg)
res4 = np.empty_like(arg)
res5 = np.empty_like(arg)

poly(res1, arg)
hope_poly(res2, arg)
numba_poly(res3, arg)
native_poly(res4, arg)
numexpr_poly(res5, arg)

assert np.allclose(res1, res2)
assert np.allclose(res1, res3)
assert np.allclose(res1, res4)
assert np.allclose(res1, res5)

In [8]:
print "python"
%timeit poly(res, arg)
print "hope"
%timeit hope_poly(res, arg)
print "numba"
%timeit numba_poly(res, arg)
print "cython"
%timeit cython_poly(res, arg)
print "cython numpy"
%timeit cython_numpy_poly(res, arg)
print "native"
%timeit native_poly(res, arg)
print "numexpr (1)"
ne.set_num_threads(1)
%timeit numexpr_poly(res, arg)
print "numexpr ({0})".format(ne.detect_number_of_cores())
ne.set_num_threads(ne.detect_number_of_cores())
%timeit numexpr_poly(res, arg)


python
100 loops, best of 3: 2.57 ms per loop
hope
10000 loops, best of 3: 29 µs per loop
numba
100 loops, best of 3: 2.66 ms per loop
cython
100 loops, best of 3: 9.97 ms per loop
cython numpy
100 loops, best of 3: 2.56 ms per loop
native
100 loops, best of 3: 2.06 ms per loop
numexpr (1)
1000 loops, best of 3: 1.33 ms per loop
numexpr (8)
1000 loops, best of 3: 550 µs per loop

In [9]:
ne.set_num_threads(8)
perf_comp_data(["poly", 
                "hope_poly", 
                "numba_poly", 
                "cython_poly", 
                "cython_numpy_poly", 
                "native_poly",
                "numexpr_poly"], 
               7*["res, arg"], rep=100)


function: hope_poly           , av. time sec:   0.00002789, min. time sec:   0.00002694, relative:       1.0
function: numexpr_poly        , av. time sec:   0.00054300, min. time sec:   0.00048995, relative:      19.5
function: native_poly         , av. time sec:   0.00204802, min. time sec:   0.00201893, relative:      73.4
function: cython_numpy_poly   , av. time sec:   0.00257111, min. time sec:   0.00251794, relative:      92.2
function: poly                , av. time sec:   0.00260139, min. time sec:   0.00251603, relative:      93.3
function: numba_poly          , av. time sec:   0.00272107, min. time sec:   0.00263000, relative:      97.5
function: cython_poly         , av. time sec:   0.00962663, min. time sec:   0.00949407, relative:     345.1

In [ ]: