详解如何利用Cython为Python代码加速


Posted in Python onJanuary 27, 2018

引言

通常,在 Python 中写循环(特别是多重循环)非常的慢,在文章 https://3water.com/article/133807.htm中,我们的元胞自动机的状态更新函数 update_state 使用了两重循环,所以我们尝试用 Cython 重构该方法。

代码

我们在同文件夹下新建一个 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):
  """更新一次状态"""
  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-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

update_state_c 函数上的两个装饰器是用来关闭 Cython 的边界检查的。

在同文件下新建一个 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 后,同文件夹下会生成一个 update.cp36-win_amd64.pyd 的文件,这就是编译好的 C 扩展。

我们修改原始的代码,首先在文件头部加入 import update as cupdate,然后修改更新方法如下

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

将原方法名就改为 update_state_py 即可,运行脚本,无异常。

测速

我们编写一个方法来测试一下使用 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 多倍。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
Python Requests安装与简单运用
Apr 07 Python
Python实现压缩和解压缩ZIP文件的方法分析
Sep 28 Python
python实现类之间的方法互相调用
Apr 29 Python
Python通过调用有道翻译api实现翻译功能示例
Jul 19 Python
python用plt画图时,cmp设置方法
Dec 13 Python
用python生成与调用cntk模型代码演示方法
Aug 26 Python
python3通过udp实现组播数据的发送和接收操作
May 05 Python
Python类super()及私有属性原理解析
Jun 15 Python
Python 实现一个计时器
Jul 28 Python
python 实现倒计时功能(gui界面)
Nov 11 Python
细说NumPy数组的四种乘法的使用
Dec 18 Python
深入浅析python3 依赖倒置原则(示例代码)
Jul 09 Python
详解Python 实现元胞自动机中的生命游戏(Game of life)
Jan 27 #Python
Python实现的栈(Stack)
Jan 26 #Python
使用python实现链表操作
Jan 26 #Python
Python中optparser库用法实例详解
Jan 26 #Python
python利用socketserver实现并发套接字功能
Jan 26 #Python
Django的HttpRequest和HttpResponse对象详解
Jan 26 #Python
Python编程实现的简单神经网络算法示例
Jan 26 #Python
You might like
在字符串指定位置插入一段字符串的php代码
2010/02/16 PHP
PHP文件操作方法汇总
2015/07/01 PHP
PHP实现重载的常用方法实例详解
2017/10/18 PHP
php过滤htmlspecialchars() 函数实现把预定义的字符转换为 HTML 实体用法分析
2019/06/25 PHP
扩展jQuery 键盘事件的几个基本方法
2009/10/30 Javascript
jquery自定义属性(类型/属性值)
2013/05/21 Javascript
node.js中的fs.readlink方法使用说明
2014/12/17 Javascript
JQuery中属性过滤选择器用法实例分析
2015/05/18 Javascript
JS简单实现String转Date的方法
2016/03/02 Javascript
用v-html解决Vue.js渲染中html标签不被解析的问题
2016/12/14 Javascript
js实现常见的工具条效果
2017/03/02 Javascript
javascript 中null和undefined区分和比较
2017/04/19 Javascript
JS表单提交验证、input(type=number) 去三角 刷新验证码
2017/06/21 Javascript
jQuery实现小火箭返回顶部特效
2020/02/03 jQuery
JavaScript的垃圾回收机制与内存管理
2020/08/06 Javascript
element-ui tree结构实现增删改自定义功能代码
2020/08/31 Javascript
JavaScript实现世界各地时间显示
2020/09/07 Javascript
vue实现单一筛选、删除筛选条件
2020/10/26 Javascript
Python实现简单的可逆加密程序实例
2015/03/05 Python
python动态参数用法实例分析
2015/05/25 Python
Python自然语言处理之词干,词形与最大匹配算法代码详解
2017/11/16 Python
解决Python selenium get页面很慢时的问题
2019/01/30 Python
Python利用requests模块下载图片实例代码
2019/08/12 Python
python 并发编程 非阻塞IO模型原理解析
2019/08/20 Python
pyenv虚拟环境管理python多版本和软件库的方法
2019/12/26 Python
tensorflow 固定部分参数训练,只训练部分参数的实例
2020/01/20 Python
python文件读取失败怎么处理
2020/06/23 Python
Python 解析库json及jsonpath pickle的实现
2020/08/17 Python
HMV日本官网:全球知名的音乐、DVD和电脑游戏零售巨头
2016/08/13 全球购物
酷瑞网络科技面试题
2012/03/30 面试题
自立自强的名人事例
2014/02/10 职场文书
廉洁家庭事迹材料
2014/05/15 职场文书
部门经理助理岗位职责
2015/04/13 职场文书
MySQL窗口函数的具体使用
2021/11/17 MySQL
mybatis源码解读之executor包语句处理功能
2022/02/15 Java/Android
python基础之//、/与%的区别详解
2022/06/10 Python