An introduction to Cython that doesn't go deep

What is Cython?

Python is by no means fast, but rather slow. Therefore, Cython is trying to speed up by converting to C / C ++.

It is decided to be fast because it is converted to a low-level language C / C ++ (which used to be a high-level language, but now it can be called a low-level language) and natively compiled.

Purpose of this article

You might get the impression that ** "Cython is difficult" ** and ** "Cython requires knowledge of C / C ++" **. The answer is ** "Yes" **.

However, the answer is premised on making full use of Cython. In fact, Cython is designed so that you don't need to know much about ** C / C ++ to get enough benefits for a little speedup **.

However, even if you use Cython blindly, you will get disappointing results such as "not very fast" and "very difficult to migrate". Based on the points around here, the purpose of this article is to enable beginners who are not familiar with C / C ++ to pick up and eat the delicious parts of Cython.

Not explained in this article

This article does not explain how to install Cython or how to write setup.py. If you search on Google, it will come out soon, so please search.

Make Cython available on Windows.

This article doesn't go into the depths of Cython, it's meant to pinch and eat delicious food, and doesn't cover the depths of Cython. Very gratefully, if you want to know the deeper part of Cython, which is a Japanese translation of the Cython documentation, see the article below.

Cython document (Japanese translation)

Cases where it is better not to speed up with Cython

Just because the processing speed is faster, it should not be speeded up if it happens, but rather it can be said that there are few places where speeding up is effective with Cython.

Speeding up other than CPU bound

The execution speed of a program is not determined solely by the simple processing speed. The only thing that can be improved by improving the processing speed is waiting (CPU bound) due to a lot of arithmetic processing, waiting for memory access (memory bound), waiting for data reading from HDD etc. (I / O bound), etc. Has almost no effect. These problems should be addressed by improving the algorithm (memoization, etc.) and threading / multi-processing.

Speed up all programs

Accelerating with Cython is easier than porting to C / C ++, but it is still burdensome. It often doesn't make much sense to work hard to speed up the entire program. It is much more efficient to speed up a function that is called 1000 times by 1% than to speed up a function that is called only once by 10%.

In other words, there is only a small part of the whole that should be accelerated.

The above two points are the basic principles and common sense of speeding up. The important thing is not to speed up the entire program, but to ** understand the causes and locations of bottlenecks and take appropriate action **. Paradoxically, the processing speed of the language is not so important, the improvement of the algorithm is more important, and the problem of execution speed can be solved by improving the algorithm in most cases.

Depending on the cause of the bottleneck, SWIG or Numba may be more suitable, so use the right person in the right place.

Code to improve with Cython

Loop processing

Python looping is slow. This is because various checks are made at the time of loop because of the degree of freedom that various types can be stored in the array. Even if you are using fast Numpy, turning the array with for will dramatically reduce the speed, and it is a good rule to avoid loop processing when using Numpy.

Arithmetic processing

Due to the degree of freedom due to the dynamically typed language, variable type checking is included for each operation. Even a simple operation a + b has to go through the __add__ method, so overhead is incurred for each operation.

Function call

Not limited to Python, function calls incur significant overhead. In particular, dynamically typed languages have a larger overhead than statically typed languages because type checks are performed even when they are assigned to the stack.

Cython starting with Jupyter (IPython)

Jupyter is the best way to implement Cython. Cython supports Jupyter's magick command, so you can easily try it on Jupyter.

On Jupyter, type the following command to enable Cython.

%load_ext Cython

Let's experiment with the Fibonacci numbers that everyone loves. First, in Python, create a Python function that finds the Fibonacci number.

def py_fib(n):
    a, b = 0.0, 1.0
    for i in range(n):
        a, b = a + b, a
    return a

Speed measurement


%timeit py_fib(1000)
>>> 10000 loops, best of 3: 66.9 µs per loop

Next, type the magic command %% cython at the beginning to create a function that has exactly the same content as the previous Python function. Again, the content is exactly the same as that of Python, only the function name is different.

%%cython
def cy_fib(n):
    a, b = 0.0, 1.0
    for i in range(n):
        a, b = a + b, a
    return a

Speed measurement


%timeit cy_fib(1000)
>>> 100000 loops, best of 3: 16 µs per loop

Just by changing the Python function to Cython, it went from 66.9µs to 16µs, which is more than 4 times faster without doing anything. Cython is fairly compatible with Python syntax, and Cython will convert it to C / C ++ as it is, unless it's too special Python code.

Let's specify the type to make it even faster.

%%cython
def cy_fib2(int n):
    a, b = 0.0, 1.0
    for i in range(n):
        a, b = a + b, a
    return a

Speed measurement


%timeit cy_fib2(1000)
>>> 1000000 loops, best of 3: 1.11 µs per loop

66.9 µs → 1.11 µs, which is 60 times faster.

The important thing here is that only the `` `def cy_fin2 (int n) ``` part is type-defined, otherwise it is exactly the same as the Python function.

In fact, Cython does type inference and automatically converts variables ʻaandb to double type and variables ʻi to int type. Even if you paste the Python code as it is, it behaves as much as possible from the original Python code, and it is converted to C / C ++ so as not to impair performance.

In Cython, ** blind typing only makes it less readable and doesn't make much sense **, but in most cases you can achieve tens of times faster by just typing a few variables.

If you type %% cython -a and execute it, Python and C / C ++ will be written together, and the lines that are taking a long time to process will be displayed in yellow.

cython.png

The legitimate use of Cython is to copy and paste the Python code without thinking about it, and preferentially type the yellow lines.

Summary

In summary, the parts that need to be optimized for speeding up are only a few functions in the program code, and only a few lines of those functions should be optimized by Cython. Therefore, Cython aims to achieve it easily while maintaining readability.

Cython is often thought to be difficult, but thanks to the efforts of Cython developers, it is almost perfectly compatible with Python. If you want to partially accelerate it, you can get enough benefits without knowing C / C ++. (In 99% of cases, just a few speedups will achieve the goal)

~~ Cython is very profound, and more explanations on how to use it will be on another occasion. ~~

Continue to Introduction to Cython without going deep -2-.

Recommended Posts

An introduction to Cython that doesn't go deep
An introduction to Cython that doesn't go deep -2-
An introduction to Word2Vec that even cats can understand
Introduction to Cython Writing [Notes]
An introduction to private TensorFlow
Introduction to Deep Learning ~ Learning Rules ~
An introduction to Python Programming
An introduction to Bayesian optimization
Deep Reinforcement Learning 1 Introduction to Reinforcement Learning
Introduction to Deep Learning ~ Backpropagation ~
[Introduction to StyleGAN] That "man who doesn't laugh" smiled unintentionally ♬
An introduction to Python that even monkeys can understand (Part 3)
An introduction to Python that even monkeys can understand (Part 1)
An introduction to Python that even monkeys can understand (Part 2)
An introduction to Mercurial for non-engineers
Introduction to Deep Learning ~ Function Approximation ~
Introduction to Deep Learning ~ Coding Preparation ~
Introduction to Deep Learning ~ Dropout Edition ~
Introduction to Deep Learning ~ Forward Propagation ~
Introduction to Deep Learning ~ CNN Experiment ~
An introduction to Python for non-engineers
[Python Tutorial] An Easy Introduction to Python
An introduction to Pandas that you can learn while suffering [Part 1]
Introduction to Deep Learning ~ Convolution and Pooling ~
An introduction to OpenCV for machine learning
Recurrent Neural Networks: An Introduction to RNN
An introduction to Python for machine learning
An Introduction to Object-Oriented-Give an object a child.
An introduction to Python for C programmers
Introduction to Deep Learning (1) --Chainer is explained in an easy-to-understand manner for beginners-
[What is an algorithm? Introduction to Search Algorithm] ~ Python ~
An introduction to machine learning for bot developers
An introduction to object-oriented programming for beginners by beginners
An amateur tried Deep Learning using Caffe (Introduction)
An introduction to statistical modeling for data analysis
Introduction to Deep Learning ~ Localization and Loss Function ~
Introduction to Python "Re" 1 Building an execution environment
An introduction to voice analysis for music apps
Introduction to Scrapy (1)
Introduction to Scrapy (3)
Introduction to Supervisor
Introduction to Tkinter 1: Introduction
Introduction to PyQt
Introduction to Scrapy (2)
[Linux] Introduction to Linux
Introduction to Scrapy (4)
Introduction to discord.py (2)
Introduction to discord.py
An introduction to Python distributed parallel processing with Ray
Reading Note: An Introduction to Data Analysis with Python
How to make an HTTPS server with Go / Gin
How to deploy a Go application to an ECS instance
An introduction to machine learning from a simple perceptron
An introduction to Web API development for those who have completed the Progate Go course