In [1]:
import hope
hope.config.optimize = True
hope.config.verbose = True
hope.config.keeptemp = True
import numba
import numpy as np
from util import perf_comp_data
from native_util import load
%load_ext cythonmagic
%load_ext version_information
%version_information numpy, Cython, numba, hope


Out[1]:
SoftwareVersion
Python2.7.8 64bit [GCC 4.2.1 Compatible Apple LLVM 5.1 (clang-503.0.40)]
IPython1.1.0
OSDarwin 13.4.0 x86_64 i386 64bit
numpy1.8.1
Cython0.20.2
numbatag: 0.13.3
hope0.3.0
Thu Dec 04 11:18:15 2014 CET

fibonacci


In [2]:
def fib(n):
    if n<2:
        return n
    return fib(n-1)+fib(n-2)
hope_fib = hope.jit(fib)
numba_fib = numba.jit(fib, nopython=False)

native_fib_mod = load("fib")
native_fib = native_fib_mod.run 

n=20
assert fib(20) == 6765
assert hope_fib(20) == 6765
assert numba_fib(20) == 6765
assert native_fib(20) == 6765


running build_ext
building 'fib' 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/workspace/virtualenvs/hope_benchmarks/lib/python2.7/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/fib.cpp
/usr/bin/clang++ -bundle -undefined dynamic_lookup -L/opt/local/lib -Wl,-headerpad_max_install_names -L/opt/local/lib/db48 ./src/fib.o -o ./fib.so

fib(int64 n)
	if (n.J < 2.J) {
		return n.J
	}
	return (fib((n.J - 1.J)) + fib((n.J - 2.J)))

Compiling following functions:
fib(int64 n)
running build_ext
building 'fib_181039868ed022600dc3388e38604df736dff187257d5d6ae4c4d3ea_0' 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/workspace/virtualenvs/hope_benchmarks/lib/python2.7/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: /var/folders/k_/ttz9cd4d3kj2kbh3lvtn6tkm0000gn/T/hopeDXfz9_/fib_181039868ed022600dc3388e38604df736dff187257d5d6ae4c4d3ea_0.cpp
/usr/bin/clang++ -bundle -undefined dynamic_lookup -L/opt/local/lib -Wl,-headerpad_max_install_names -L/opt/local/lib/db48 /var/folders/k_/ttz9cd4d3kj2kbh3lvtn6tkm0000gn/T/hopeDXfz9_/fib_181039868ed022600dc3388e38604df736dff187257d5d6ae4c4d3ea_0.o -o /var/folders/k_/ttz9cd4d3kj2kbh3lvtn6tkm0000gn/T/hopeDXfz9_/fib_181039868ed022600dc3388e38604df736dff187257d5d6ae4c4d3ea_0.so


In [3]:
%%cython

cimport cython

@cython.boundscheck(False)
@cython.wraparound(False)
cpdef int cython_fib(int n):
    if n<2:
        return n
    return cython_fib(n-1)+cython_fib(n-2)

assert cython_fib(20) == 6765


building '_cython_magic_d4ac66e2963d3320a31dcc65e2809bf2' 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/opt/local/Library/Frameworks/Python.framework/Versions/2.7/include/python2.7 -c'
clang: /Users/jakeret/.ipython/cython/_cython_magic_d4ac66e2963d3320a31dcc65e2809bf2.c
/usr/bin/clang -bundle -undefined dynamic_lookup -L/opt/local/lib -Wl,-headerpad_max_install_names -L/opt/local/lib/db48 /Users/jakeret/.ipython/cython/Users/jakeret/.ipython/cython/_cython_magic_d4ac66e2963d3320a31dcc65e2809bf2.o -o /Users/jakeret/.ipython/cython/_cython_magic_d4ac66e2963d3320a31dcc65e2809bf2.so

In [4]:
%timeit fib(20)
%timeit hope_fib(20)
%timeit numba_fib(20)
%timeit cython_fib(20)
%timeit native_fib(20)


100 loops, best of 3: 2.59 ms per loop
10000 loops, best of 3: 40.6 µs per loop
100 loops, best of 3: 2.55 ms per loop
10000 loops, best of 3: 42.5 µs per loop
10000 loops, best of 3: 41.4 µs per loop

In [7]:
perf_comp_data(["fib", "hope_fib", "numba_fib", "cython_fib", "native_fib"],
               5*["n"])


function: native_fib          , av. time sec:   0.00003982, min. time sec:   0.00003886, relative:       1.0
function: hope_fib            , av. time sec:   0.00004315, min. time sec:   0.00003815, relative:       1.1
function: cython_fib          , av. time sec:   0.00004911, min. time sec:   0.00004101, relative:       1.2
function: numba_fib           , av. time sec:   0.00260401, min. time sec:   0.00255513, relative:      65.4
function: fib                 , av. time sec:   0.00291204, min. time sec:   0.00247192, relative:      73.1

quicksort


In [8]:
def qsort_kernel(a, lo, hi):
    i = lo
    j = hi
    if False: return a
    while i < hi:
        pivot = a[(lo+hi) // 2]
        while i <= j:
            while a[i] < pivot:
                i += 1
            while a[j] > pivot:
                j -= 1
            if i <= j:
                tmp = a[i]
                a[i] = a[j]
                a[j] = tmp
                i += 1
                j -= 1
        if lo < j:
            qsort_kernel(a, lo, j)
        lo = i
        j = hi
    return a

hope_qsort_kernel = hope.jit(qsort_kernel)
numba_qsort_kernel = numba.jit(qsort_kernel)

native_qsort_kernel_mod = load("qsort_kernel")
native_qsort_kernel = native_qsort_kernel_mod.run


running build_ext
building 'qsort_kernel' 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/qsort_kernel.cpp
/usr/bin/clang++ -bundle -undefined dynamic_lookup -L/opt/local/lib -Wl,-headerpad_max_install_names -L/opt/local/lib/db46 ./src/qsort_kernel.o -o ./qsort_kernel.so


In [16]:
def numpy_qsort_kernel(a, lo, hi):
    np.sort(a)

In [17]:
%%cython

cimport cython
import numpy as np
cimport numpy as np

@cython.boundscheck(False)
@cython.wraparound(False)
def cython_qsort_kernel(np.ndarray[np.double_t, ndim=1] a, int lo, int hi):
    cdef int i = lo
    cdef int j = hi
    cdef double pivot = 0
    cdef double tmp = 0.0
    if False: return a
    while i < hi:
        pivot = a[(lo+hi) // 2]
        while i <= j:
            while a[i] < pivot:
                i += 1
            while a[j] > pivot:
                j -= 1
            if i <= j:
                tmp = a[i]
                a[i] = a[j]
                a[j] = tmp
                i += 1
                j -= 1
        if lo < j:
            cython_qsort_kernel(a, lo, j)
        lo = i
        j = hi
    return a

In [18]:
lst = np.random.random(5000)

In [19]:
psorted = qsort_kernel(lst.copy(), 0, len(lst)-1)
hsorted = hope_qsort_kernel(lst.copy(), 0, len(lst)-1)
#nsorted = numba_qsort_kernel(lst.copy(), 0, len(lst)-1)
csorted = cython_qsort_kernel(lst.copy(), 0, len(lst)-1)
nasorted = native_qsort_kernel(lst.copy(), 0, len(lst)-1)

In [20]:
assert np.all(psorted[:-1] <= psorted[1:])
#assert np.all(hope_qsort_kernel[:-1] <= hope_qsort_kernel[1:])
#assert np.all(numba_qsort_kernel[:-1] <= numba_qsort_kernel[1:])
#assert np.all(cython_qsort_kernel[:-1] <= cython_qsort_kernel[1:])

%timeit qsort_kernel(lst.copy(), 0, len(lst)-1)
%timeit hope_qsort_kernel(lst.copy(), 0, len(lst)-1)
#%timeit numba_qsort_kernel(lst.copy(), 0, len(lst)-1)
%timeit cython_qsort_kernel(lst.copy(), 0, len(lst)-1)
%timeit native_qsort_kernel(lst.copy(), 0, len(lst)-1)
%timeit np.sort(lst.copy())


10 loops, best of 3: 22.4 ms per loop
1000 loops, best of 3: 334 µs per loop
1000 loops, best of 3: 1.4 ms per loop
1000 loops, best of 3: 303 µs per loop
1000 loops, best of 3: 248 µs per loop

In [21]:
a = lst.copy()

lo = 0
hi = len(lst)-1

perf_comp_data(["hope_qsort_kernel", 
                "qsort_kernel", 
                #"numpy_qsort_kernel", 
                "cython_qsort_kernel", 
                "native_qsort_kernel"],
               5*["a, lo, hi"], rep=100, extra_setup="from __main__ import lst;a = lst.copy()")


function: native_qsort_kernel , av. time sec:   0.00029302, min. time sec:   0.00029182, relative:       1.0
function: hope_qsort_kernel   , av. time sec:   0.00033617, min. time sec:   0.00033379, relative:       1.1
function: cython_qsort_kernel , av. time sec:   0.00143504, min. time sec:   0.00140619, relative:       4.9
function: qsort_kernel        , av. time sec:   0.02197444, min. time sec:   0.02172208, relative:      75.0

pi sum


In [23]:
def pisum():
    for j in range(1, 501):
        sum = 0.0
        f = 0.0
        for k in range(1, 10001):
            sum += 1.0/(k*k)
    return sum
def pisum_opt():
    for j in range(1, 501):
        sum = 0.0
        f = 0.0
        for k in range(1, 10001):
            f += 1.
            sum += 1.0/(f*f)
    return sum

hope_pisum = hope.jit(pisum)
hope_pisum_opt = hope.jit(pisum_opt)

numba_pisum = numba.jit(pisum, nopython=True)
numba_pisum_opt = numba.jit(pisum_opt, nopython=True)

native_pisum_mod = load("pisum")
native_pisum = native_pisum_mod.run

native_pisum_opt_mod = load("pisum_opt")
native_pisum_opt = native_pisum_opt_mod.run


assert abs(pisum()-1.644834071848065) < 1e-6
assert abs(hope_pisum()-1.644834071848065) < 1e-6
assert abs(hope_pisum_opt()-1.644834071848065) < 1e-6
assert abs(numba_pisum()-1.644834071848065) < 1e-6
assert abs(native_pisum()-1.644834071848065) < 1e-6
assert abs(native_pisum_opt()-1.644834071848065) < 1e-6


running build_ext
building 'pisum' 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/pisum.cpp
/usr/bin/clang++ -bundle -undefined dynamic_lookup -L/opt/local/lib -Wl,-headerpad_max_install_names -L/opt/local/lib/db46 ./src/pisum.o -o ./pisum.so

running build_ext
building 'pisum_opt' 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/pisum_opt.cpp
/usr/bin/clang++ -bundle -undefined dynamic_lookup -L/opt/local/lib -Wl,-headerpad_max_install_names -L/opt/local/lib/db46 ./src/pisum_opt.o -o ./pisum_opt.so


In [24]:
%load_ext cythonmagic


The cythonmagic extension is already loaded. To reload it, use:
  %reload_ext cythonmagic

In [25]:
%%cython

cimport cython

@cython.boundscheck(False)
@cython.wraparound(False)
@cython.locals(f=float)
def cython_pisum():
    cdef double sum = 0.0
    for j in range(1, 501):
        sum = 0.0
        f = 0.0
        for k in range(1, 10001):
            sum += 1.0/(k*k)
    return sum

@cython.boundscheck(False)
@cython.wraparound(False)
@cython.locals(f=float)
def cython_pisum_opt():
    cdef double sum = 0.0
    for j in range(1, 501):
        sum = 0.0
        f = 0.0
        for k in range(1, 10001):
            f += 1.
            sum += 1.0/(f*f)
    return sum


assert abs(cython_pisum()-1.644834071848065) < 1e-6
assert abs(cython_pisum_opt()-1.644834071848065) < 1e-6

In [26]:
%timeit pisum()
%timeit pisum_opt()
%timeit hope_pisum()
%timeit hope_pisum_opt()
%timeit numba_pisum()
%timeit numba_pisum_opt()
%timeit cython_pisum()
%timeit cython_pisum_opt()
%timeit native_pisum()
%timeit native_pisum_opt()


1 loops, best of 3: 493 ms per loop
1 loops, best of 3: 641 ms per loop
10 loops, best of 3: 21.4 ms per loop
10 loops, best of 3: 21.6 ms per loop
10 loops, best of 3: 40.8 ms per loop
10 loops, best of 3: 21.8 ms per loop
1 loops, best of 3: 284 ms per loop
10 loops, best of 3: 21.1 ms per loop
10 loops, best of 3: 21.1 ms per loop
10 loops, best of 3: 21.3 ms per loop

In [27]:
perf_comp_data(["pisum", "pisum_opt", 
                "hope_pisum", "hope_pisum_opt", 
                "numba_pisum", "numba_pisum_opt", 
                #"cython_pisum", 
                "cython_pisum_opt",
                "native_pisum", "native_pisum_opt",], 
               None, rep=100)


function: cython_pisum_opt    , av. time sec:   0.02122343, min. time sec:   0.02094698, relative:       1.0
function: native_pisum_opt    , av. time sec:   0.02158451, min. time sec:   0.02108502, relative:       1.0
function: native_pisum        , av. time sec:   0.02167845, min. time sec:   0.02090883, relative:       1.0
function: numba_pisum_opt     , av. time sec:   0.02173293, min. time sec:   0.02095199, relative:       1.0
function: hope_pisum_opt      , av. time sec:   0.02241504, min. time sec:   0.02135611, relative:       1.1
function: hope_pisum          , av. time sec:   0.02270293, min. time sec:   0.02136111, relative:       1.1
function: numba_pisum         , av. time sec:   0.04188490, min. time sec:   0.04017806, relative:       2.0
function: pisum               , av. time sec:   0.49351048, min. time sec:   0.48015594, relative:      23.3
function: pisum_opt           , av. time sec:   0.64186037, min. time sec:   0.61331892, relative:      30.2

In [17]: