How to Use Cython to accelerate Python code and cythonpython
Introduction
Generally, writing a loop (especially multiple loops) in Python is very slow. In the article http://www.bkjia.com/article/132.167.htm, our new function update_state of the metacell automatically uses two repeated loops. Therefore, we try to use Cython to reconstruct this method.
Code
Create an update. pyx file in the same folder and write the following content:
Import numpy as np cimport cythonDTYPE = np. floatctypedef np. float_t DTYPE_tdef update_state (np. ndarray [DTYPE_t, ndim = 2] cells): return update_state_c (cells) @ cython. boundscheck (False) @ cython. wraparound (False) cdef np. ndarray [DTYPE_t, ndim = 2] update_state_c (np. ndarray [DTYPE_t, ndim = 2] cells): "Update status once" cdef unsigned int I cdef unsigned int j cdef np. ndarray [DTYPE_t, ndim = 2] buf = np. zeros (cells. shape [0], cells. shape [1]), dtype = DTYPE) cdef DTYPE_t neighbor_num for I in range (1, cells. shape [0]-1): for j in range (1, cells. shape [0]-1): # calculate the number of surviving cells around the cell neighbor_num = cells [I, J-1] + cells [I, j + 1] + cells [I + 1, j] + cells [I-1, j] + \ cells [I-1, J-1] + cells [I-1, j + 1] + \ cells [I + 1, J-1] + cells [I + 1, j + 1] if neighbor_num = 3: buf [I, j] = 1 elif neighbor_num = 2: buf [I, j] = cells [I, j] else: buf [I, j] = 0 return buf
The update_state_c function is used to disable the Cython boundary check.
Create a new setup. py file in the same file
import numpy as npfrom distutils.core import setupfrom Cython.Build import cythonizesetup( name="Cython Update State", ext_modules=cythonize("update.pyx"), include_dirs=[np.get_include()])
Because the NumPy header file is used in the Cython file, we need to include it in setup. py.
After you execute python setup. py build_ext -- inplace, a file of update. cp36-win_amd64.pyd is generated in the same folder, which is the compiled C extension.
To modify the original code, first add import update as cupdate to the file header, and then modify the update method as follows:
Def update_state (self): "updated once" self. cells = cupdate. update_state (self. cells) self. timer + = 1
Change the original method name to update_state_py and run the script without exception.
Speed Measurement
Let's write a method to test the speed improvement of Cython.
def test_time(): import time game = GameOfLife(cells_shape=(60, 60)) t1 = time.time() for _ in range(300): game.update_state() t2 = time.time() print("Cython Use Time:", t2 - t1) del game game = GameOfLife(cells_shape=(60, 60)) t1 = time.time() for _ in range(300): game.update_state_py() t2 = time.time() print("Native Python Use Time:", t2 - t1)
Run this method and output the following on my computer:
Cython Use Time: 0.007000446319580078
Native Python Use Time: 4.342248439788818
The speed has increased by more than 600 times.
The above is all the content of this article. I hope it will be helpful for your learning and support for helping customers.