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.
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.
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)
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.
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.
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%.
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.
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.
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.
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.
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 ʻaand
b 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.
The legitimate use of Cython is to copy and paste the Python code without thinking about it, and preferentially type the yellow lines.
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