Feb 17, 2013

Speeding up Python performance with Cython (I)

Cython is a programming language which creates C/C++ extensions for Python, that is, is able to translate some parts of a Python program into C code, and in this way, increasing considerably the execution time of a Python program. In addition, provides some predefined constructions that you can use directly when you develop in Cython.

Let's see a Python method which takes care of calculating all prime numbers within a range (calculate_primes.py).

def calculate_primes(limit):
    primes = []
    number = 0
    divisor = 0

    for number in range(limit):
        for divisor in range(2, number+1):
            if number % divisor == 0 and number == divisor:
                primes.append(number)
                break
            elif number % divisor == 0 and number != divisor:
                break

    return primes


Now let's import this module in another program and run it in order to work out the time spent in searching for all prime numbers between 2 and 10000 (the application will be executed five times and averaged it).

$ cat test.py 
from timeit import Timer  

timer = Timer("calculate_primes(10000)",
              "from calculate_primes import calculate_primes")
print sum(timer.repeat(repeat=5, number=1)) / 5


$ python test.py 
1.7978372097


The next step will be to compile this program with Cython in order to generate C extensions for our program. So as to install Cython, you have a couple of options: either to grab directly its source code from the web page of the project, or install it from some repository. In my case, I am going to download its source code and thereby, to be able to have the most recent version (0.18 at present).

After downloading and uncompressing it, you will be able to install it on your system by running the setup.py script, or as in my case, just decompressing it on the home directory and using that path later. Also point out that you must have installed on your system all tools needed to compile C/C++ programs (for example, the package build-essential in case of Ubuntu).

$ mkdir cython ; cd cython

cython$ wget http://cython.org/release/Cython-0.18.zip ; unzip Cython-0.18.zip


The first test will be to compile the module called calculate_primes with Cython, so as to generate on the one hand a C file, and on the other, a module loadable by Python. First up, you need to change the extension of the module from py to pyx. And to compile it, you might do it by hand, but it is much better to create a tiny script responsible of accomplishing it.

cython$ cp -a calculate_primes.py calculate_primes1.pyx

cython$ cat setup.py 
import sys
sys.path.insert(0, "/home/javi/cython/Cython-0.18")
from distutils.core import setup
from distutils.extension import Extension
from Cython.Distutils import build_ext

setup(
    cmdclass = {'build_ext': build_ext},
    ext_modules = [Extension("calculate_primes1", ["calculate_primes1.pyx"])]
)


No comments:

Post a Comment