Skip to content

Instantly share code, notes, and snippets.

@aronnem
Created February 8, 2012 17:01
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save aronnem/1771057 to your computer and use it in GitHub Desktop.
Save aronnem/1771057 to your computer and use it in GitHub Desktop.
Trying out methods for changing calculations inside a cython loop
# copying http://docs.cython.org/src/tutorial/cdef_classes.html
cdef class Function:
cpdef double evaluate(self, double x) except *:
return 0
cdef class func0(Function):
cpdef double evaluate(self, double x) except *:
return basefunc0(x)
cdef class func1(Function):
cpdef double evaluate(self, double x) except *:
return basefunc1(x)
cdef double basefunc0(double x):
return x*x
cdef double basefunc1(double x):
return x*x*x
def pybasefunc0(x):
return x*x
def pybasefunc1(x):
return x*x*x
# attempting to use enum/function pointers
cdef double (*funcList[2])(double)
funcList[0] = &basefunc0
funcList[1] = &basefunc1
# "reference" for fastest speed - functions are hard coded
def cy_calc(double x, int function_id, int n):
cdef Py_ssize_t k
cdef double theResult
cdef double invn = 1.0/n
if function_id == 0:
for k in range(n):
theResult = basefunc0(x + k*invn)
else:
for k in range(n):
theResult = basefunc1(x + k*invn)
return theResult
# cleaner implemetation (use cdef class), but somewhat slower
def cy_calc_cdef(double x, Function f, int n):
cdef Py_ssize_t k
cdef double theResult
cdef double invn = 1.0/n
for k in range(n):
theResult = f.evaluate(x + k*invn)
return theResult
# func pointer implementation
def cy_calc_fptr(double x, int selected_func, int n):
cdef Py_ssize_t k
cdef double theResult
cdef double invn = 1.0/n
for k in range(n):
theResult = funcList[selected_func](x + k*invn)
return theResult
# reference python-only version
def py_calc(x, f, n):
invn = 1.0/n
for k in range(n):
theResult = f(x + k*invn)
return theResult
from datetime import datetime
def time_one_method(ntrial, niter, method, value, selected_func):
t0 = datetime.now()
for k in range(ntrial):
z = method(value, selected_func, niter)
return datetime.now()-t0
def run_timing(ntrial=100, niter=1234567, value=2.0):
# do only 1/100 as many reps for python and scale it
# (it is very slow)
print 'python ref: ' + \
str(time_one_method(ntrial/100, niter,
py_calc, value, pybasefunc0)*100)
print 'cython ref: ' + \
str(time_one_method(ntrial, niter, cy_calc, value, 0))
print 'cython cdef: ' + \
str(time_one_method(ntrial, niter, cy_calc_cdef, value, func0()))
print 'cython fPtr: ' + \
str(time_one_method(ntrial, niter, cy_calc_fptr, value, 0))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment