Mixed programming with Python#

Is Python slow for numerical computing?#

Task: Fill a NumPy array with function values.

Python implementation#

from math import sin

import numpy as np

n = 2000
a = np.zeros((n, n))
xcoor = np.arange(0, 1, 1 / float(n))
ycoor = np.arange(0, 1, 1 / float(n))


def f(x, y):
    return sin(x**2 + y)
%%time
for i in range(n):
    for j in range(n):
        a[i, j] = f(xcoor[i], ycoor[j])
CPU times: user 1.23 s, sys: 9.73 ms, total: 1.24 s
Wall time: 1.25 s

Timings#

Version

Time (normalised)

Fortran/C/C++ version

1.0

NumPy vectorized evaluation of f

3.0

Python loop version (numpy.sin)

140

Python loop version (math.sin)

350

Conclusions#

  • Python loops over arrays are extremely slow

  • NumPy vectorization may be sufficient

  • However, sometimes plain loops in Fortran/C/C++ are easier

Why are version in the compiled languages faster?#

Optimizations of C, C++, and Fortran:

  • Compilers do a good job for C, C++, and Fortran.

  • The type system makes agressive optimization possible.

  • Examples: code inlining, loop unrolling, and memory prefetching.

In contrast, in Python we have:

  • No compiler.

  • No type declaration of variables.

  • No inlining and no loop unrolling.

  • Probably inefficient in Python:

    def f(a, b):
        return a + b
    

Overview of mixed programming tools#

Extending vs embedding Python#

Python can be mixed with other languages in two ways:

  1. By extending Python with libraries and functions written in other languages

  2. By embedding, i.e. calling Python from inside a program written in another language

We only consider extending Python. This has two main use cases:

  1. Accessing functions in existing libraries written in C or C++, to avoid re-inventing existing tools

  2. Speeding up a Python program by migrating slow code (e.g. loops) to C or C++

Summary of mixed-programming tools#

  • Hand written wrapper code using the Python-C-API;

    • [+] General, low level control, no need for additional libraries and tools

    • [-] Time consuming, significant overhead

  • ctypes

    • Provides C compatible data types, and allows calling functions in shared libraries.

    • [+] Part of the standard Python library, no need for compiling, all wrapper code is written in Python

    • [-] Low support for C++, Python wrapper code introduces overhead

  • Cython

    • Extends the Python language with elements from C

    • can write pure Python

    • Python/Cython code is compiled and available as a Python module

    • Lots of advanced tools and possibilities

  • Numba

    • Uses Just in Time compilation (JIT) to speed up Python code

    • [+] (Almost) fully automatic

    • [o] Seems magical, which can make debugging more tricky

    • [-] Needs to be installed as runtime dependency

  • pybind11

    • [+] powerful for complex bindings to C++

    • Good for C++ experts who need Python bindings