Python Programming: Getting Started

Python is an excellent programming language. It’s easy to learn and it’s general enough that you can do nearly everything with it.

Coding

But the standard implementation of Python, what you get with most flavours of Linux is CPython and for things like array processing (or Lists), it that fast. Oh you can overcome that with NumPy; that provides arrays, plus code for linear algebra, fast Fourier transforms and random numbers and it runs very fast. 

There are several alternatives to CPython, for instance pypy but Cython is a static compiler for Python, not quite the same. It produces fast code though, so lets have a look at it and see how well it works.

I’ve adapted a Swift program for evaluating Pi by throwing virtual darts at a virtual dart board inside a square. If the dart lies within the circular area, it counts as a hit. Otherwise it hits one of the four corner pieces and counts as a miss. The total of hits/total thrown = 0.25 * pi, so multiplying by four gives the value of pi. Yes I know Python has pi in the math.pi library. You can see this from within the Python REPL.

<pre>

Python

>>>from math import pi

>>>print pi

3.14159265359

</pre>

 

But this is to show the speed gains possible with Cython. Here is the program to generate a value for pi, that I called pi.py.

 

<pre>

import random

 

nPoints = 10000000

nPointsInside = 0

 

for i in range(nPoints):

    x = random.random() * 2 – 1

    y = random.random() * 2 – 1

    if x * x + y * y <= 1:

        nPointsInside += 1

 

pi = (4.0 * nPointsInside) / nPoints

print ‘pi = ‘,pi,’ for ‘,nPoints

</pre>

 

With Python 2.7.6, this took 4.09 seconds and even slower with Python 3.4.3 at 5.68 seconds.

 

Meet Cython

Cython is an optimising static compiler for both the Python programming language and the extended Cython programming language that’s based on Pyrex. We won’t worry about Pyrex. Cython is based on C and uses C types instead of Python’s dynamic typing. Almost all of Python is supported by Cython.

To install Cython, on Ubuntu or Debian do

<pre>

sudo apt-get install cython

</pre>

 

On my Ubuntu 14.04, it’s a 40 Mb download.

 

Cython prerequisites

To compile with Cython, using the distutils method you need three files:

  1. py
  2. An extension file with a .pyx extension e.g. pi.pyx
  3. A python program to import from the extension and call a function.

 

setup.py

This does the donkeywork of building by calling a function cythonize to compile the extension code. It’s sort of traditional to call it setup.py but you can use any name so long as it has a .py extension.

<pre>

from distutils.core import setup

from Cython.Build import cythonize

 

setup(

  name = ‘Calc Pi Program’,

  ext_modules = cythonize(“pi.pyx”),

)

</pre>

 

pi.pyx

I’ve moved most of the code from the earlier program into an extension with a function.

<pre>

import random

 

def calcpi(int n):

    cdef int nPointsInside = 0

    cdef double x,y

    for i in range(n):

        x = random.random() * 2 – 1

        y = random.random() * 2 – 1

        if x * x + y * y <= 1:

            nPointsInside += 1

 

    return (4.0 * nPointsInside) / n

</pre>

 

Note also I’ve defined types for the parameter n and the local variables nPointsInside, x and y.

Finally there’s testpi.py which is short.

<pre>

from pi import calcpi

nPoints = 10000000

pi = calcpi(nPoints)

print (‘pi = ‘,pi,’ for ‘,nPoints)

</pre>

 

Before running for the first time, you need to build the extension and this command does that.

<pre>

python setup.py build_ext –inplace

</pre>ipython

 

That generates a pi.c from pi.pyx then compiles it with gcc into pi.so. If you prefer Python3 that will work but if you build with it, you must also run the test program with it as well. Talking of which, you run the test program with this command:

<pre>

python testpi.py

</pre>

Timings

I ran the original pi.py under both Python 2.7 and 3.4 using ipython and the times were 4.13 seconds (P2.7) and 5.69 seconds (P3).

The Cython versions took 2.46 seconds (P2) and 2.34 seconds (P3).

The ipython/ipython3 commands to time it are %timeit %run testpi.py.

Cython is more than able to speed up Python code, but the speed gains depends partly as to how C like you can make your code. However you are free to cythonize as little or as much as you need. It’s pretty clever and of course free.

If your code does a lot of numeric list work, you should go down the NumPy route first then see if Cython can speed it up.

 

Post a Comment

Your email address will not be published.