详解如何利用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 相关文章推荐
使用paramiko远程执行命令、下发文件的实例
Oct 01 Python
利用nohup来开启python文件的方法
Jan 14 Python
python七夕浪漫表白源码
Apr 05 Python
python3 线性回归验证方法
Jul 09 Python
pycharm 批量修改变量名称的方法
Aug 01 Python
python获取array中指定元素的示例
Nov 26 Python
python实现五子棋游戏(pygame版)
Jan 19 Python
关于多元线性回归分析——Python&SPSS
Feb 24 Python
深度学习入门之Pytorch 数据增强的实现
Feb 26 Python
PyPDF2读取PDF文件内容保存到本地TXT实例
May 12 Python
聊聊Python中关于a=[[]]*3的反思
Jun 02 Python
Python进行区间取值案例讲解
Aug 02 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
计数器详细设计
2006/10/09 PHP
PHP基于DOM创建xml文档的方法示例
2017/02/08 PHP
PHP实现链表的定义与反转功能示例
2018/06/09 PHP
PHP安装BCMath扩展的方法
2019/02/13 PHP
phpQuery采集网页实现代码实例
2020/04/02 PHP
PhpStorm2020 + phpstudyV8 +XDebug的教程详解
2020/09/17 PHP
CSS JavaScript 实现菜单功能 改进版
2008/12/09 Javascript
javascript 写类方式之七
2009/07/05 Javascript
IE中radio 或checkbox的checked属性初始状态下不能选中显示问题
2009/07/25 Javascript
clientX,pageX,offsetX,x,layerX,screenX,offsetLeft区别分析
2010/03/12 Javascript
jQuery中fadeIn、fadeOut、fadeTo的使用方法(图片显示与隐藏)
2013/05/08 Javascript
jQuery弹出层插件Lightbox_me使用指南
2015/04/21 Javascript
javascript中undefined与null的区别
2015/08/16 Javascript
JavaScript中instanceof运算符的使用示例
2016/06/08 Javascript
JS框架之vue.js(深入三:组件1)
2016/09/29 Javascript
JS插件plupload.js实现多图上传并显示进度条
2016/11/29 Javascript
基于JS代码实现简单易用的倒计时 x 天 x 时 x 分 x 秒效果
2017/07/13 Javascript
Vue+element 解决浏览器自动填充记住的账号密码问题
2019/06/11 Javascript
[00:47]TI7不朽珍藏III——沙王不朽展示
2017/07/15 DOTA
Python编程实现微信企业号文本消息推送功能示例
2017/08/21 Python
Python实现利用最大公约数求三个正整数的最小公倍数示例
2017/09/30 Python
PyCharm 常用快捷键和设置方法
2017/12/20 Python
Linux CentOS7下安装python3 的方法
2018/01/21 Python
通过Python模块filecmp 对文件比较的实现方法
2018/06/29 Python
Tensorflow tensor 数学运算和逻辑运算方式
2020/06/30 Python
Python浮点型(float)运算结果不正确的解决方案
2020/09/22 Python
多个版本的python共存时使用pip的正确做法
2020/10/26 Python
H&M旗下高端女装品牌:& Other Stories
2018/05/07 全球购物
EJB包括(SessionBean,EntityBean)说出他们的生命周期,及如何管理事务的?
2013/02/17 面试题
医学检验专业大学生求职信
2013/11/18 职场文书
初中生物教学反思
2014/01/10 职场文书
高三学习决心书
2014/03/11 职场文书
幼儿园新年寄语
2014/04/03 职场文书
优秀乡村医生事迹材料
2014/05/28 职场文书
学习党的群众路线实践活动思想汇报
2014/09/12 职场文书
生日寿星公答谢词
2015/09/29 职场文书