<kbd id='woaibaidu'></kbd><address id='woaibaidu'><style id='woaibaidu'></style></address><button id='woaibaidu'></button>

          当前位置:主页 > 脚本专栏 > python >
            详解如何利用Cython为Python代码加速
            2018-01-29 22:13 发布 次浏览

          引言

          通常,在 Python 中写循环(特别是多重循环)十分的慢,在文章 http://www.jb51.net/article/133807.htm中,我们的元胞自念头的形态更新函数 update_state 运用了两重循环,所以我们实验用 Cython 重构该办法。

          代码

          我们在同文件夹下新建1个 update.pyx 文件,写入以下内容

          import numpy as np 
          cimport numpy as np 
          cimport cython
          
          
          DTYPE = np.float
          ctypedef np.float_t DTYPE_t
          
          def 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):
            """更新1次形态"""
            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):
                # 盘算该细胞四周的存活细胞数
                
                neighbor_num = cells[i, j⑴] + cells[i, j+1] + cells[i+1, j] + cells[i⑴, j] +\
                        cells[i⑴, j⑴] + cells[i⑴, j+1] +\
                        cells[i+1, j⑴] + 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
          
          

          update_state_c 函数上的两个装潢器是用来封闭 Cython 的界限反省的。

          在同文件下新建1个 setup.py 文件

          import numpy as np
          from distutils.core import setup
          from Cython.Build import cythonize
          
          setup(
            name="Cython Update State",
            ext_modules=cythonize("update.pyx"),
            include_dirs=[np.get_include()]
          )
          
          

          由于在 Cython 文件中运用了 NumPy 的头文件,所以我们需求在 setup.py 将其包括出来。

          履行 python setup.py build_ext --inplace 后,同文件夹下会生成1个 update.cp36-win_amd64.pyd 的文件,这就是编译好的 C 扩大。

          我们修正原始的代码,首先在文件头部参加 import update as cupdate,然后修正更新办法以下

          def update_state(self):
            """更新1次形态"""
            self.cells = cupdate.update_state(self.cells)
            self.timer += 1

          将原办法名就改成 update_state_py 便可,运转剧本,无异常。

          测速

          我们编写1个办法来测试1下运用 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)
          

          运转该办法,在我的电脑上输入以下

          Cython Use Time: 0.007000446319580078
          Native Python Use Time: 4.342248439788818

          速度提升了 600 多倍。

          以上就是本文的全部内容,希望对各人的学习有所协助,也希望各人多多支持聚合网。