Getting started with cython
Remarks#
What is Cython?
The Cython programming language enriches Python by C-like static typing, the ability to directly call C functions, and several other features. This allows to reach C-level performance while still using a Python-like syntax.
How does it work?
Cython code is compiled using the cython source-to-source compiler to create C or C++ code, which in turn can be compiled using a C compiler. This allows to create extensions that can be imported from Python or executables.
The main performance gain Cython can reach in contrast to pure Python stems from bypassing the CPython API. For example when adding two integers, Python performs a type check for each variable, finds an add function that satisfies the found types, and calls that function. In the Cython-generated C code, the types are already know and only one function call to is made. Hence, Cython especially shines for mathematic problems in which the types are clear.
How do I use it to speed up my code?
A common use case, when trying to speed up a program using Cython, is to profile the code and move the computationally expensive parts to compiled Cython modules. This allows to retain Python syntax for the bulk of the code and apply the speedup where it is most needed.
Installing Cython
To use Cython two things are needed.The Cython package itself, which contains the cython
source-to-source compiler and Cython interfaces to several C and Python libraries (for example numpy). To compile the C code generated by the cython
compiler, a C compiler is needed.
Step 1: Installing Cython
System Agnostic
Cython can be installed with several system agnostic package management systems. These include:
-
PyPI via pip or easy_install:
$ pip install cython $ easy_install cython
-
anaconda using conda:
$ conda install cython
-
Enthought canopy using the enpkg package manager:
$ enpkg cython
Also the source code can be downloaded from github and installed manually using:
$ python setup.py install
Ubuntu, Debian
For Ubuntu the packages cython
and cython3
are available. Note that these provide an older version than the installation options mentioned above.
$ apt-get install cython cython3
Windows
For Windows, a .whl file that can be installed using pip is provided by a third party. Details on installing a .whl file on Windows can be found here.
Step 2: Installing a C Compiler
To compile the C files generated by Cython, a compiler for C and C++ is needed. The gcc compiler is recommended and can be installed as follows.
Ubuntu, Debian
The build-essential
package contains everything that is needed. It can be installed from the repositories using:
$ sudo apt-get install build-essential
MAC
The XCode developer tools contain a gcc like compiler.
Windows
MinGW (Minimalist GNU for Windows) contains a Windows version of gcc. The compiler from Visual Studio can also be used.
Hello World
A Cython pyx file needs to be translated to C code (cythonized) and compiled before it can be used from Python. A common approach is to create an extension module which is then imported in a Python program.
Code
For this example we create three files:
hello.pyx
contains the Cython code.test.py
is a Python script that uses the hello extension.setup.py
is used to compile the Cython code.
hello.pyx
from libc.math cimport pow
cdef double square_and_add (double x):
"""Compute x^2 + x as double.
This is a cdef function that can be called from within
a Cython program, but not from Python.
"""
return pow(x, 2.0) + x
cpdef print_result (double x):
"""This is a cpdef function that can be called from Python."""
print("({} ^ 2) + {} = {}".format(x, x, square_and_add(x)))
test.py
# Import the extension module hello.
import hello
# Call the print_result method
hello.print_result(23.0)
setup.py
from distutils.core import Extension, setup
from Cython.Build import cythonize
# define an extension that will be cythonized and compiled
ext = Extension(name="hello", sources=["hello.pyx"])
setup(ext_modules=cythonize(ext))
Compiling
This can be done by, using cython hello.pyx
to translate the code to C and then compile it using gcc
. An easier way is to let distutils handle this:
$ ls
hello.pyx setup.py test.py
$ python setup.py build_ext --inplace
$ ls
build hello.c hello.cpython-34m.so hello.pyx setup.py test.py
The shared object (.so) file can be imported and used from Python, so now we can run the test.py
:
$ python test.py
(23.0 ^ 2) + 23.0 = 552.0