Created
February 8, 2012 17:01
-
-
Save aronnem/1771057 to your computer and use it in GitHub Desktop.
Trying out methods for changing calculations inside a cython loop
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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