Faster Python with Cython and PyPy: Part 2

Tom Craven, Technical Lead

Last week I started this two-part blog series about increasing the speed of Python through Cython and PyPy. While we already discussed the effects of Cython, I wanted to continue the discussion with a look at PyPy and then a contrast of both PyPy and Cython.

How Fast Is PyPy?

PyPy is an alternative Python interpreter and just-in-time (JIT) compiler that is highly compatible (subject to a few caveats) with the CPython interpreter. It is designed for speed and efficiency and uses a tracing JIT compiler to optimize frequently executed parts of the program at runshutterstock_449846935time, thus increasing the execution speed.

PyPy runs regular Python programs; in general, no modifications need to be made to Python code to allow it to run on PyPy. Owing to the nature of the JIT compiler, it needs time to analyze frequently executed parts of the program, so it works best on programs that run for longer than a few seconds.

Perhaps the biggest hurdle to using PyPy in a production system is its lack of support for CPython extension modules. According to the PyPy documentation, extension module support is experimental and often runs much slower than in CPython. This means that some third-party libraries that have C extension modules might not work on PyPy—the scientific computing library NumPy is a notable example. Having said this, PyPy is able to run the majority of popular Python frameworks and libraries, such as Django, Flask, and SQLAlchemy.

The PyPy Wikipedia page and the PyPy website provide plenty of information on what PyPy is and how to use it; the latter also has a nice section that shows a list of benchmarks and their speed improvements over CPython.

Test Program: Numerical Integration

My main objective in doing this exercise was to understand how the tools work, and to be able to compare the differences in syntax and code structure between them. With that in mind, I chose to write a simple numerical integration program, which is based on an example given in the Cython documentation. The full project source, including installation and Cython build instructions, can be found on Bitbucket.

In the following code listing, the pure Python implementation is on the left, while the Cython version is on the right.
cythonpypy2
The Cython code differs from pure Python in the following ways:

Cython modules have a .pyx file extension instead of .py. The Cython build process translates them into intermediate C source files then compiles them using the system’s C compiler.

Cython code looks like Python code with added type declarations. Type declarations for variables, function arguments, and return values are optional, but adding them gives Cython enough information to translate into more optimized C code.

Cython allows easy linking to C libraries. At line 3, I’ve used the cimport statement to import the native libc math library instead of the Python math library, which improves performance.

Cython allows native C functions, which have less overhead than Python functions when they are called, and therefore execute faster. At line 5, I’ve defined f as a native function using the cdef statement. A downside to using native cdef functions is that they are not accessible by Python code outside the Cython module – effectively they are private.

Lines 9-11 in the integrate_f function define the variables. Defining i as an integer at line 11 allows Cython to translate the for loop at line 12 into a native C for loop, which improves performance. If the type of i was not specified, the loop would execute more slowly because the type of i would have to be checked at each iteration.

Benchmark Results

I tested the following three implementations of the algorithm:

  • CPython: The pure Python implementation running in the standard CPython interpreter
  • CPython + Cython: The Cython implementation running in the standard CPython interpreter
  • PyPy: The pure Python implementation running in the PyPy interpreter

In order to measure the speed of program execution for each implementation, I wrote a program to call integrate_f 500 times using an N value of 50,000, and recorded the execution time over several runs.

I ran the tests on a 2015 Macbook Pro, using CPython 2.7.9, Cython 0.24, GCC 4.2.1 and PyPy 2.5.1 (compatible with CPython 2.7.9).

The following table shows the benchmark results:

table

The CPython + Cython implementation is the fastest; it is 44 times faster than the CPython implementation. This is an impressive speed improvement, especially considering that the Cython code is very close to the original Python code in its design.

The PyPy implementation is 16 times faster than the CPython implementation, and about 3 times slower than the Cython implementation. This is fascinating since PyPy is running the exact same pure Python code as the CPython implementation – it shows the power of PyPy’s JIT compiler.

And The Winner Is…

I’ve enjoyed learning about Cython and PyPy and am impressed by the speed gains that are possible with only a small amount of programming effort. Speed is certainly addictive, and it’s hard to go back to running my 9-second Python program when I know the Cython one runs in 0.2 seconds!

My numerical integration test program is, of course, a toy problem, and it should be remembered that benchmarking results can vary considerably depending on the algorithms. In a real project, I would likely use NumPy or another specialized third-party library to perform my calculations.

CPython C extension modules, the Cython language and the PyPy interpreter are deep and interesting subjects in their own right and I’ve only scratched the surface in this blog post. Each tool has its own pros and cons, and may be a great fit for one project and a bad fit for another.

Having experimented with both tools, I am more likely to use Cython for speed-critical parts of programs in the future. The slow parts of the code can be identified by profiling and refactoring into a Cython module, which could be written to only contain the functions that needed to be optimized.

PyPy seems like it would be more of a quick fix, swapping out the CPython interpreter for PyPy without modifying a project’s existing code base. I would be concerned, however, that somewhere down the line a third-party library would be required for some functionality, and that it would turn out to be incompatible with PyPy. You could very possibly paint yourself into a corner.

I hope that I’ve managed to provide a valuable introduction to the world of Cython and PyPy. I already knew that Python was awesome—now I know that it can be fast too!

 

Cardinal Peak
Learn more about our Audio & Video capabilities.

Dive deeper into our IoT portfolio

Take a look at the clients we have helped.

We’re always looking for top talent, check out our current openings. 

Contact Us

Please fill out the contact form below and our engineering services team will be in touch soon.

We rely on Cardinal Peak for their ability to bolster our patent licensing efforts with in-depth technical guidance. They have deep expertise and they’re easy to work with.
Diego deGarrido Sr. Manager, LSI
Cardinal Peak has a strong technology portfolio that has complemented our own expertise well. They are communicative, drive toward results quickly, and understand the appropriate level of documentation it takes to effectively convey their work. In…
Jason Damori Director of Engineering, Biamp Systems
We asked Cardinal Peak to take ownership for an important subsystem, and they completed a very high quality deliverable on time.
Matt Cowan Chief Scientific Officer, RealD
Cardinal Peak’s personnel worked side-by-side with our own engineers and engineers from other companies on several of our key projects. The Cardinal Peak staff has consistently provided a level of professionalism and technical expertise that we…
Sherisse Hawkins VP Software Development, Time Warner Cable
Cardinal Peak was a natural choice for us. They were able to develop a high-quality product, based in part on open source, and in part on intellectual property they had already developed, all for a very effective price.
Bruce Webber VP Engineering, VBrick
We completely trust Cardinal Peak to advise us on technology strategy, as well as to implement it. They are a dependable partner that ultimately makes us more competitive in the marketplace.
Brian Brown President and CEO, Decatur Electronics
The Cardinal Peak team started quickly and delivered high-quality results, and they worked really well with our own engineering team.
Charles Corbalis VP Engineering, RGB Networks
We found Cardinal Peak’s team to be very knowledgeable about embedded video delivery systems. Their ability to deliver working solutions on time—combined with excellent project management skills—helped bring success not only to the product…
Ralph Schmitt VP, Product Marketing and Engineering, Kustom Signals
Cardinal Peak has provided deep technical insights, and they’ve allowed us to complete some really hard projects quickly. We are big fans of their team.
Scott Garlington VP Engineering, xG Technology
We’ve used Cardinal Peak on several projects. They have a very capable engineering team. They’re a great resource.
Greg Read Senior Program Manager, Symmetricom
Cardinal Peak has proven to be a trusted and flexible partner who has helped Harmonic to deliver reliably on our commitments to our own customers. The team at Cardinal Peak was responsive to our needs and delivered high quality results.
Alex Derecho VP Professional Services, Harmonic
Yonder Music was an excellent collaboration with Cardinal Peak. Combining our experience with the music industry and target music market, with Cardinal Peak’s technical expertise, the product has made the mobile experience of Yonder as powerful as…
Adam Kidron founder and CEO, Yonder Music
The Cardinal Peak team played an invaluable role in helping us get our first Internet of Things product to market quickly. They were up to speed in no time and provided all of the technical expertise we lacked. They interfaced seamlessly with our i…
Kevin Leadford Vice President of Innovation, Acuity Brands Lighting
We asked Cardinal Peak to help us address a number of open items related to programming our systems in production. Their engineers have a wealth of experience in IoT and embedded fields, and they helped us quickly and diligently. I’d definitely…
Ryan Margoles Founder and CTO, notion