« Previous 1 2 3 Next »
High-performance Python – compiled code and C interface
Step Lively
Cython Examples
Cython can accept almost any valid Python source file to produce C code. Compiling the C code is fairly simple. The first step in using Cython is the easiest: Select the code you want and put it into a separate file. You can have more than one function per file if you like.
The second step is to create the setup.py
file, which is like a makefile for Python. It defines what Python file you want to compile into a shareable library and is where you can put options (e.g., compile options) you want to use. After compiling, be sure to test the code.
Here, I use two examples from a Cython tutorial [13]. The first is a simple Hello World example, and the second is a summation example that uses a loop.
Hello World
The Python code to be compiled in the helloworld.pyx
file is
print("Hello World")
which is just about the simplest one-line Python script you can have. As previously mentioned, you need to create a setup.py
file that is really a Python makefile:
from distutils.core import setup from Cython.Build import cythonize setup( ext_modules=cythonize("helloworld.pyx") )
The first two lines are fairly standard for a Python setup.py
file. After that, the setup
command builds the binary (shared object). In this case, the command is to cythonize
the helloworld.pyx
file. To make life easier, be sure to put this file in the same directory as the code.
The system I used had Ubuntu 18.04 (with updates) and the Anaconda Python distribution. To build the binary, enter
$ python3 setup.py build_ext --inplace
The output is shown in Listing 3. Note that the command line uses setup.py
as the "configuration" for building the binary (shared object). In the output, you will see paths that correspond to the system I used. Don't worry about this because setup.py
takes care of the paths.
Listing 3
Binary Build
$ python3 setup.py build_ext --inplace Compiling helloworld.py because it changed. [1/1] Cythonizing helloworld.pyx /home/laytonjb/anaconda3/lib/python3.7/site-packages/Cython/Compiler/Main.py:367: FutureWarning: Cython directive 'language_level' not set, using 2 for now (Py2). This will change in a later release! File: /home/laytonjb/HPC-PYTHON-1/helloworld.pyx tree = Parsing.p_module(s, pxd, full_module_name) running build_ext building 'helloworld' extension creating build creating build/temp.linux-x86_64-3.7 gcc -pthread -B /home/laytonjb/anaconda3/compiler_compat -Wl,--sysroot=/ -Wsign-compare -DNDEBUG -g -fwrapv -O3 -Wall -Wstrict-prototypes -fPIC -I/home/laytonjb/anaconda3/include/python3.7m -c helloworld.c -o build/temp.linux-x86_64-3.7/helloworld.o gcc -pthread -shared -B /home/laytonjb/anaconda3/compiler_compat -L/home/laytonjb/anaconda3/lib -Wl,-rpath=/home/laytonjb/anaconda3/lib -Wl,--no-as-needed -Wl,--sysroot=/ build/temp.linux-x86_64-3.7/helloworld.o -o /home/laytonjb/HPC-PYTHON-1/helloworld.cpython-37m-x86_64-linux-gnu.so
Now I can test the compiled Cython shared object:
>>> import helloworld Hello World
It worked! These are the basic steps for creating a compiled binary (shared object) of Python code.
Summing
To begin, I'll take some simple Python code from the Numba example and compute the sum of a one-dimensional list. Although I'm sure better code is out there for computing a sum, this example will teach you how to do a more mathematical example.
For this example, a simple function in the sum.pyx
file computes the sum:
def sum(x): total = 0 for i in range(x.shape[0]): total += x[i] return total
The code is compiled the same way as the Hello World code, with a change to the Python function in setup.py
to cythonize sum.pyx
. The code in Listing 4 tests the module in a Jupyter notebook.
Listing 4
Summation Test
import sum import numpy x = numpy.arange(10_000_000); %time sum.sum(x) CPU times: user 1.37 s, sys: 0 ns, total: 1.37 s Wall time: 1.37 s
Notice that sum
is the object and sum.sum
is the function within the object, which means you can put more than one function in your Python code. Also notice that the time for running the code is about the same as the pure Python itself. Although you can optimize Cython code by, for example, employing OpenMP, I won't discuss that here.
« Previous 1 2 3 Next »
Buy this article as PDF
(incl. VAT)