1. code with pure python, then build a python module with distutils

The following code was took directly from cython official site. I don't want ot waste typing. 

Imagine a simple “hello world” script in a file hello.pyx:

def say_hello_to(name):
    print("Hello %s!" % name)

The following could be a corresponding setup.py script:

from distutils.core import setup
from Cython.Build import cythonize

setup(
  name = 'Hello world app',
  ext_modules = cythonize("hello.pyx"),
)

To build, run python setup.py build_ext --inplace. Then simply start a Python session and do from hello import say_hello_to and use the imported function as you see fit.

Around 35% improvment without really doing anything. 

2. using cdef to further speed up

With additional type declarations, this might look like:

def f(double x):
    return x**2-x

def integrate_f(double a, double b, int N):
    cdef int i
    cdef double s, dx
    s = 0
    dx = (b-a)/N
    for i in range(N):
        s += f(a+i*dx)
    return s * dx

Since the iterator variable i is typed with C semantics, the for-loop will be compiled to pure C code. Typing as and dx is important as they are involved in arithmetic withing the for-loop; typing b and N makes less of a difference, but in this case it is not much extra work to be consistent and type the entire function.

This results in a 4 times speedup over the pure Python version.

cdef Typing function

cdef typing a function can avoid the overhead of calling a python function, but with cdef modifying a function, it can no longer called in other python file. 

In other words, it can only be called internally. See the following: 

cdef double f(double x) except? -2:
    return x**2-x

Speedup: 150 times over pure Python.

Note: if this function is not only called internally, but also outside. cpdef would be your choise, which will create two functions, one for internal, the other for outside. 

3. call c function

Calling c functions requires to port the corresponding functions. Fortunately, cython has already ported some of the standard C library for you. 

I wil introduce how to port a c lib later.

See 

from libc.stdlib cimport atoi

cdef parse_charptr_to_py_int(char* s):
    assert s is not NULL, "byte string value is NULL"
    return atoi(s)   # note: atoi() has no error detection!

You can find a complete list of these standard cimport files in Cython’s source package Cython/Includes/. It also has a complete set of declarations for CPython’s C-API. For example, to test at C compilation time which CPython version your code is being compiled with, you can do this:

from cpython.version cimport PY_VERSION_HEX

print PY_VERSION_HEX >= 0x030200F0 # Python version >= 3.2 final

Cython also provides declarations for the C math library:

from libc.math cimport sin

cdef double f(double x):
    return sin(x*x)

Note: you can find what libs are included, and can also how to do it yourself. In ubuntu, it is in /usr/local/lib/python2.7/dist-package/Cython/Includes

This is only a learning note for now. Later, I will introduce how to use numpy and cython for speeding up, which could be immediately useful to those that are already familar with numpy. 


Tags: Cython

Posted in Cython |

Leave a Reply