Easy Python code compilation for blazingly fast applications
· Follow
Published in · 7 min read · May 22, 2022
--
Python is very easy to work with; clear syntax, the interpreter and duck-typing allow you to develop very quickly. There are some downsides though: if you don’t have to adhere to a strict syntax, then Python has to do some extra work to get your code to run, causing some functions e.g. to execute very slowly because it has to do all those checks again and again.
Combine the ease and speed of developing with Python with the speed of C: the best of both worlds
In this article we’ll take a “slow” function from a vanilla Python project and make it 30x faster. We do this by using a package called Cython that will convert our Python-code to a compiled, superfast piece of C-code that we can directly import into our project again.
A package called CythonBuilder will automatically Cythonize Python code for us in just 2 steps. With CythonBuilder we’ll Cythonize a function from an example project we’ll define below. Let’s code!
For those unfamiliar with Cython and CythonBuilder we’ll answer some exploratory questions. Then we’ll define our example project. We’re going to be using the command line so read up on that if you’re unfamiliar:
What is Cython / why use Cython?
Cython converts Python-code to a file that contains instructions for the CPU. The Python interpreter doesn’t have to perform any check anymore on this file; it can just run it. This results in a major performance increase. Check the article below for more detailed information on how Python works under the hood and how it compares to C:
When you Cythonize a piece of code you add extra information to your code; defining types e.g. Then the code is compiled so that Python doesn’t have to perform the extra checks. Again, check the article above for a more in-depth analysis.
How does Cython work
Just like you write Python code in a .py
file, you write Cython code in a .pyx
files. Cython will then convert these files to either a .so file or a .pyd file(depending on your OS). These files can be directly imported into your python project again:
Can all code be optimized by compiling?
Not all code is better off compiled. Awaiting the response of an API is not faster in a C-package for example. In short: we focus on _CPU-heavy_ tasks that require a lot of calculating. Read more in the article below for a more clear distinction.
CythonBuilder — automating Cythonizing
How do you actually Cythonize your .pyx
files? This process is pretty complex; you have to create a setup.py
, define all your packages and then run some commands (see the article below). Instead, we’re going to use CythonBuilder: a package that automates everything for us: build your .pyx
file in one command!
Our project contains a function that, for some reason, calculates a number of primes. This function takes a lot of computations that we can optimize.
Lets first install cythonbuilder with pip install cythonbuilder
and then define the regular prime-calculating function
Preparation — the vanilla Python primecalculation function
The function is pretty simple: we’ll pass a number to the function and it returns the number of prime numbers between 0 and the target number:
This function is pure Python. It could be optimized a bit more but the goal is to have a function that performs a lot of calculations. Let’s check out how long it takes this function to find the number of primes between 0 and 100.000:
PurePython: 29.4883812 seconds
Step 1. — Cythonize
In this part we’ll introduce Cython. We’ll copy the code of our function and save it into a file called cy_count_primes.pyx
(notice the .pyx
).
Next we cd projectfolder
and call cythonbuilder build
. This will find all of the pyx-files in the projectfolder and build them. The result is a .pyd
file on Windows or a .so
file on Linux. This file is a compiled version of our Python function that we can directly import in our project:
from someplace.cy_count_primes import count_primes
print(count_primes(100_000))
Lets check out how it performs:
PurePython: 29.4883812 seconds
CyPython : 14.0540504 seconds (2.0982 faster than PurePython
Already over 2 times faster! Notice that we haven’t actually changed anything to our Python code. Let’s optimize the code.
Interfaces:
As you’ll notice even your IDE can inspect the imported files. It knows which functions are present and which arguments are required even though the file is compiled. This is possible because CythonBuilder also builds .pyi files; these are interface files that provide the IDE with information abouth the pyd files.
Step 2 — add types
In this part we add types to the cy_count_primes.pyx
file and then build it again:
As you see we define our function with cpdef
(both accessible by c and p(ython), tell it to return an int
(before count_primes
) and that it expects an the limit
argument to be an int
.
Next, on lines 2,3 and 4, we define the types for some of the variables that are used in the loops; nothing fancy.
Now we can cythonbuilder build
again and time our function again:
PurePython: 29.4883812 seconds
CyPython : 14.0540504 seconds (2.0982 faster than PurePython
Cy+Types : 1.1600970 seconds (25.419 faster than PurePython
That’s a very impressive speedup!
The reason why this is so much faster is not within the scope of this article but it has to do with the way Python stores its variables in memory. It’s pretty inefficient compared to C so our C-compiled code can run much faster. Check out this article that dives deep in how Python and C differ from each other under the hood (and why C is so much faster).
Bonus — compilation options
We’ve already improved code execution by 25x but I think we can squeeze a bit more out of it. We’ll do this with compiler directives. These take a little bit of explanation:
Because Python is an interpreted language it has to perform a lot of checks at run-time, for example if your program divides by zero. In C, a compiled language, these check happen at build-time; these errors are spotted when compiling. The advantage is that your program can run more efficiently since it doesn’t have to perform these checks at runtime.
With compiler directives we can disable all these checks, but only if we know we don’t need them. In the example below we upgrade our previous code with 4 decorators that:
- prevent checks on ZeroDivisionError
- prevent checks on IndexErrors (calling myList[5] when the list only contains 3 items)
- prevents checks on isNone
- prevents wraparound; prevents extra checks that are required for calling a list relative to the end like mylist[-5])
Let’s re-build our code (cythonbuilder build
) again and see what time-save skipping all these check offer
PurePython: 29.4883812 seconds
CyPython : 14.0540504 seconds (2.0982 faster than PurePython
Cy+Types : 1.1600970 seconds (25.419 faster than PurePython
Cy+Options: 0.9562186 seconds (30.838 faster than PurePython
We’ve shaved off another 0.2 seconds!
Even more speed?
It is possible to speed up our code even more by making use of our multiple cores. Check out the article below for a guide on how to apply multi-processing and threading in Python programs. Also check out this article that shows you how to multi-process Cython code and explains Cython’s annotation files: graphical overviews of which parts of your code can be further optimized. Very convenient!
CythonBuilder makes it easy to speed up our Python code using Cython.
As we’ve seen just copying our Python code and building doubles the execution speeds! The greatest speed increase is by adding types; resulting in a 25x speed increase relative to vanilla Python.
I hope everything was as clear as I hope it to be but if this is not the case please let me know what I can do to clarify further. In the meantime, check out my other articles on all kinds of programming-related topics like these:
- Why Python is so slow and how to speed it up
- Git for absolute beginners: understanding Git with the help of a video game
- Docker for absolute beginners: the difference between an image and a container
- Docker for absolute beginners — what is Docker and how to use it (+ examples)
- Virtual environments for absolute beginners — what is it and how to create one (+ examples)
- Create and publish your own Python package
- Create Your Custom, private Python Package That You Can PIP Install From Your Git Repository
- Create a fast auto-documented, maintainable, and easy-to-use Python API in 5 lines of code with FastAPI
- Dramatically improve your database insert speed with a simple upgrade
Happy coding!
— Mike
P.S: like what I’m doing? Follow me!
FAQs
How do I speed up my Cython code? ›
- Step 1: write our python function with our file extension . py.
- Step 2: write a Cython version of this function in a file extension . pyx.
- Step 3: Create the setup file . py and point to the . pyx file.
- Step 4: Go to the setup.py directory and run the setup. This will generate C/C++ bytecode and other files.
- Tutorial to convert python code to cython. ...
- from math import sin def f(x): return sin(x**2) def integrate_f(a, b, N): s = 0 dx = (b-a)/N for i in range(N): s += f(a+i*dx) return s * dx.
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.
How do I compile a Cython file? ›- The cython command takes a . py or . pyx file and compiles it into a C/C++ file.
- The cythonize command takes a . py or . pyx file and compiles it into a C/C++ file. It then compiles the C/C++ file into an extension module which is directly importable from Python.
- Creating function. ...
- Eliminate unessential operations. ...
- Avoid declaring unnecessary variables. ...
- Use appropriate algorithms. ...
- Learn the concept of dynamic programming. ...
- Minimize the use of If-Else. ...
- Break the loops when necessary.
The C code output by Cython is not generally quite as fast as hand-written C, but it's often close. Given below are two code snippets with the observed output. What is the explanation for the observed behavior?
Is Cython C or C++? ›If you are going to wrap a C or C++ library: For C, the easiest option is Cython. You could use the Python C API directly, but that involves a lot of boilerplate. For C++, you can use Cython, but Cython has limited C++ support, and you need to reimplement all the headers using Cython's syntax.
Why not use Cython? ›Most security bugs in the wild are due to memory unsafety, and using C and C++ makes it far too easy to introduce these bugs. Cython inherits this problem, which means it's very difficult to write secure code with Cython.
Is Cython as fast as Java? ›Even Cython will be several times slower than a carefully tuned C/C++, Java, C# or Go program for most practical problems. And at least in the case of C/C++ it'll also likely use several times more RAM.
How do I speed up Python code? ›- Use proper data structure. Use of proper data structure has a significant effect on runtime. ...
- Decrease the use of for loop. ...
- Use list comprehension. ...
- Use multiple assignments. ...
- Do not use global variables. ...
- Use library function. ...
- Concatenate strings with join. ...
- Use generators.
Which is better Python or Cython? ›
Cython is faster. It is slower. Cython understands C specifications with Python and which additionally supports calling C/C++ functions. Understands the code written using python specifications.
What is the fastest Cython? ›Cython code runs fastest when in 'pure C'
If you have a function in C labeled with the cdef keyword, with all of its variables and inline function calls to other things that are pure C, it will run as fast as C can go.
In this chapter we will learn about Cython’s multithreading features to access thread-based parallelism. Our focus will be on the prange Cython function, which allows us to easily transform serial for loops to use multiple threads and tap into all available CPU cores.
Can Cython compile any Python code? ›Cython allows us to compile Python code, the result is dynamic libraries that can be used as python modules too.
How fast do programmers write code? ›Some sources say that the average typing speed worldwide is 40 wpm (word per minute). And there's this answer from Quora saying that the respectable typing speed for programmers should be 50 wpm.
How do you speed up VS code performance? ›- Open the Command Palette (Ctrl+Shift+P).
- Run the Preferences: Configure Runtime Arguments command.
- This command will open a argv. json file to configure runtime arguments. You might see some default arguments there already.
- Add "disable-hardware-acceleration": true .
- Restart VS Code.
When Cython is slower, it's probably due to type conversions, and possibly exacerbated by a lack of type annotations. Also, if you use C datastructures in Cython, that'll tend to be faster than using Python datastructures in Cython.
How fast is Cython than Python? ›Note that regular Python takes more than 500 seconds for executing the above code while Cython just takes around 1 second. Thus, Cython is 500x times faster than Python for summing 1 billion numbers.
What compiler does Cython use? ›A Cython program is compiled to C code, which is further compiled to machine code, so the virtual machine is used only briefly when the program is loaded.
Can Cython be slower than Python? ›You'd think this would make for slower performance due to the simple fact that there is more code. Still, you'll see that the Cython code is way faster than the Python code.
Can you mix Python and Cython? ›
You can still write regular code in Python, but to speed things up at run time Cython allows you to replace some pieces of the Python code with C. So, you end up mixing both languages together in a single file. Note that you can imagine that everything in Python is valid in Cython, but with some limitations.
Does Cython use Python type hints? ›Pure Python syntax in Cython
Type hints for our variables are done in the conventional Python way. For instance, the variable n is declared at the class level with a Python type hint. Likewise, function signatures use Python-style type hints to indicate what they take in and return.
- Nim. Nim. Nim is a statically typed compiled systems programming language. ...
- Fortran. Fortran. ...
- IronPython. IronPython. ...
- Eclipse Ceylon. Eclipse Ceylon. ...
- Vyper. Vyper. ...
- Apache Groovy. The Apache Software Foundation. ...
- Dart. Dart Language. ...
- Swift. Apple.
Python is a powerful object-oriented scripting language. Jython is useful because it provides the productivity features of a mature scripting language and, unlike Python, runs in any environment that supports a Java virtual machine (JVM).
Which is faster Numba or Cython? ›Numba is the simplest one, you must only add some instructions to the beginning of the code and is ready to use. But it has limitations, which are less and less with each version. With Cython, you can feel like an ace of optimization. It is a little slower to digest since it has many options.
Does Cython use C++? ›Cython is a programming language that blends Python with the static type system of C and C++. cython is a compiler that translates Cython source code into efficient C or C++ source code.
Which JVM is the fastest? ›The fastest of them all is GraalVM EE 17, but the difference compared to OpenJDK 8/OpenJDK 17 is marginal. Here is a graph with the typical 256-byte message latency for the various JDK variants used (lower is better):
What are the C types in Cython? ›Types. The Cython language uses the normal C syntax for C types, including pointers. It provides all the standard C types, namely char , short , int , long , long long as well as their unsigned versions, e.g. unsigned int ( cython. uint in Python code).
Why Python is so fast? ›Because Python is a dynamically typed programming language, it compiles faster than other languages but runs slower.
Can Python be as fast as Java? ›Java vs Python - Speed
In terms of speed, Java is faster than Python as it is a compiled language. It takes less time to execute a code. Python is an interpreted language and it determines the type of data at run time which makes it slower comparatively.
What is the difference between PyPy and Cython? ›
Cython is a source code translator that is available as an open-source under Apache License from the PyPI repository. PyPi (Python Package Index) is a Python software repository, and should not be confused with PyPy. PyPy is an implementation of Python (2.7. 13 and 3.5.
What is the top 1 hardest programming language? ›Malbolge. This language is so hard that it has to be set aside in its own paragraph. Malbolge is by far the hardest programming language to learn, which can be seen from the fact that it took no less than two years to finish writing the first Malbolge code.
What is the strongest coding language? ›C++, JavaScript, and Java are powerful programming languages for this case. Mobile app development. C++ and Java can provide excellent performance for the mobile apps you're building.
Is C++ or Python faster? ›C++ is faster than Python because it is statically typed, which leads to a faster compilation of code. Python is slower than C++, it supports dynamic typing, and it also uses the interpreter, which makes the process of compilation slower.
Do you need to know C for Cython? ›Little to none. Cython isn't about writing C, but annotating Python to produce C. The cdef is one of the most powerful annotations, but requires so little C knowledge, you can just pick it up from the cython docs and not know it's C.
Which is the fastest data type in Python? ›Python Tuple
Tuples are generally faster than the list data type in Python because it cannot be changed or modified like list datatype.
- Bring the parts of your code you want to convert to c into a separate file.
- Give type information and let Cython know what you want to use in Python and what you don't.
- compile the separate file using a setup.py file.
Cython will get you good speedups on almost any pure Python code, without too much extra effort at all. The key thing is the more loops, the more data crunching, the more Cython can help. Lets look at result showing how much speed Cython have for different factorial values. And the speed improvements are more than 30x.
How to install Cython in Python? ›- Open your Linux terminal or shell.
- Type “ pip install cython ” (without quotes), hit Enter.
- If it doesn't work, try "pip3 install cython" or “ python -m pip install cython “.
- Wait for the installation to terminate successfully.
You can launch a notebook session by typing jupyter notebook in the command line and you can load the Cython magic by typing %load_ext cython in a cell. As already mentioned earlier, the %%cython magic can be used to compile and load the Cython code inside the current session.
Does Cython support classes? ›
Based on what Python calls a “built-in type”, however, Cython supports a second kind of class: extension types, sometimes referred to as “cdef classes” due to the Cython language keywords used for their declaration.
How to build Cython modules? ›- def add(x, y): result = x + y. return result.
- from my_module import add. z = add(4, 5)
- from distutils.core import setup. from Cython.Build import cythonize. setup( ...
- $ python3 setup.py build_ext --inplace. running build_ext. building 'my_module' extension. ...
- from my_module import add. z = add(4, 5)
Python has a global lock (the GIL) to ensure that data related to the Python interpreter is not corrupted. It is sometimes useful to release this lock in Cython when you are not accessing Python data.
Why is C so much faster than Python? ›C is a faster language compared to Python as it is compiled. Python programs are usually slower than C programs as they are interpreted. In C, the type of the various variables must be declared when they are created, and only values of those particular types must be assigned to them.
Does NumPy need Cython? ›You can use NumPy from Cython exactly the same as in regular Python, but by doing so you are losing potentially high speedups because Cython has support for fast access to NumPy arrays. Let's see how this works with a simple example.
Is compiled Python as fast as C? ›Python is a popular, beginner-friendly language. It's also an interpreted language, which makes it easy to use but slower than a compiled language such as C or C++.
Is there a way to speed up Python code? ›- Use proper data structure. Use of proper data structure has a significant effect on runtime. ...
- Decrease the use of for loop. ...
- Use list comprehension. ...
- Use multiple assignments. ...
- Do not use global variables. ...
- Use library function. ...
- Concatenate strings with join. ...
- Use generators.
One good reason is that it is a pure compiler and this is just not as easy to use during development. Another good reason is that it just isn't core Python - CPython is the real thing. You can simply put Cython into the same basket as all the other alternatives - Jython, a Java JVM implemention; IronPython, a C# .
What is one of the downsides of using Cython? ›Most security bugs in the wild are due to memory unsafety, and using C and C++ makes it far too easy to introduce these bugs. Cython inherits this problem, which means it's very difficult to write secure code with Cython. And even if security isn't a concern, memory corruption bugs are a pain to debug.
Is Cython faster than Java? ›Even Cython will be several times slower than a carefully tuned C/C++, Java, C# ... | Hacker News. Even Cython will be several times slower than a carefully tuned C/C++, Java, C# or Go program for most practical problems. And at least in the case of C/C++ it'll also likely use several times more RAM.
What is the most popular tool used to speed up Python programs? ›
PyPy and CPython are some of the existing examples which try to increase the execution speed of Python but you can do this yourself also if you just follow some tips and tricks on how to improve your coding skills so that you will be writing efficient code and not wasting any memory or CPU time.
What is the fastest speed in Python? ›Speed settings can be set between 1 (slowest) to 10 (fastest). But if you set the speed to 0, it has a special meaning — turn off animation and go as fast as possible.
Is Cython faster than PyPy? ›Because of its JIT compiler, the PyPy is faster than CPython.
What is the difference between Cython and CPython? ›CPython is the implementation of the language called “Python” in C. Python is an interpreted programming language. Hence, Python programmers need interpreters to convert Python code into machine code. Whereas Cython is a compiled programming language.
Who uses Cython? ›Uses. Cython is particularly popular among scientific users of Python, where it has "the perfect audience" according to Python creator Guido van Rossum. Of particular note: The free software SageMath computer algebra system depends on Cython, both for performance and to interface with other libraries.
Does Cython speed up pandas? ›We will see a speed improvement of ~200 when we use Cython and Numba on a test function operating row-wise on the DataFrame . Using pandas. eval() we will speed up a sum by an order of ~2.