详解如何利用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 列表(List)操作方法详解
Mar 11 Python
Python实现的Google IP 可用性检测脚本
Apr 23 Python
Python yield 使用浅析
May 28 Python
CentOS6.5设置Django开发环境
Oct 13 Python
Python使用QQ邮箱发送Email的方法实例
Feb 09 Python
pandas 实现字典转换成DataFrame的方法
Jul 04 Python
django框架基于模板 生成 excel(xls) 文件操作示例
Jun 19 Python
python实现共轭梯度法
Jul 03 Python
Python爬虫库BeautifulSoup的介绍与简单使用实例
Jan 25 Python
python中return不返回值的问题解析
Jul 22 Python
详解pyqt5的UI中嵌入matplotlib图形并实时刷新(挖坑和填坑)
Aug 07 Python
在Windows下安装配置CPU版的PyTorch的方法
Apr 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
用PHP生成静态HTML速度快类库
2007/03/18 PHP
php堆排序实现原理与应用方法
2015/01/03 PHP
php格式化金额函数分享
2015/02/02 PHP
php 使用expat方式解析xml文件操作示例
2019/11/26 PHP
PHP 实现 JSON 数据的编码和解码操作详解
2020/04/22 PHP
JavaScript 对象、函数和继承
2009/07/07 Javascript
锋利的jQuery 要点归纳(三) jQuery中的事件和动画(上:事件篇)
2010/03/24 Javascript
js constructor的实际作用分析
2011/11/15 Javascript
jQuery截取指定长度字符串代码
2014/08/21 Javascript
js获取元素外链样式的方法
2015/01/27 Javascript
jquery+html5时钟特效代码分享(可设置闹钟并且语音提醒)
2020/03/30 Javascript
js实现全国省份城市级联下拉菜单效果代码
2015/09/07 Javascript
jquery实现横向图片轮播特效代码分享
2015/11/19 Javascript
bootstrap下拉菜单使用方法解析
2017/01/13 Javascript
Vue + Webpack + Vue-loader学习教程之功能介绍篇
2017/03/14 Javascript
vue实现消息的无缝滚动效果的示例代码
2017/12/05 Javascript
Angular实现搜索框及价格上下限功能
2018/01/19 Javascript
jQuery实现文本显示一段时间后隐藏的方法分析
2019/06/20 jQuery
Vue.js递归组件实现组织架构树和选人功能
2019/07/04 Javascript
JavaScript forEach中return失效问题解决方案
2020/06/01 Javascript
vue+canvas实现拼图小游戏
2020/09/18 Javascript
[00:32]2018DOTA2亚洲邀请赛出场——LGD
2018/04/04 DOTA
python中如何使用正则表达式的非贪婪模式示例
2017/10/09 Python
Python udp网络程序实现发送、接收数据功能示例
2019/12/09 Python
Pytorch 之修改Tensor部分值方式
2019/12/27 Python
Python下利用BeautifulSoup解析HTML的实现
2020/01/17 Python
pycharm中如何自定义设置通过“ctrl+滚轮”进行放大和缩小实现方法
2020/09/16 Python
购买大码女装:Lane Bryant
2016/09/07 全球购物
德国机场停车位比较和预订网站:Ich-parke-billiger
2018/01/08 全球购物
Habitat家居英国官方网站:沙发、家具、照明、厨房和户外
2019/12/12 全球购物
用C或者C++语言实现SOCKET通信
2015/02/24 面试题
廉政教育心得体会
2014/01/01 职场文书
教学实习自我评价
2014/01/28 职场文书
2014年幼儿园个人工作总结
2014/11/10 职场文书
2015年医生个人工作总结
2015/04/25 职场文书
vue 数字翻牌器动态加载数据
2022/04/20 Vue.js