详解如何利用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 相关文章推荐
详解Django框架中用context来解析模板的方法
Jul 20 Python
python 动态加载的实现方法
Dec 22 Python
Python基于列表list实现的CRUD操作功能示例
Jan 05 Python
详谈Python中列表list,元祖tuple和numpy中的array区别
Apr 18 Python
flask-restful使用总结
Dec 04 Python
python 自定义对象的打印方法
Jan 12 Python
Python常用爬虫代码总结方便查询
Feb 25 Python
介绍一款python类型检查工具pyright(推荐)
Jul 03 Python
Python 之 Json序列化嵌套类方式
Feb 27 Python
JAVA及PYTHON质数计算代码对比解析
Jun 10 Python
python使用隐式循环快速求和的实现示例
Sep 11 Python
Python极值整数的边界探讨分析
Sep 15 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版(5)
2006/10/09 PHP
Mysql的GROUP_CONCAT()函数使用方法
2008/03/28 PHP
Views rows style模板重写代码
2011/05/16 PHP
PHP中将数组转成XML格式的实现代码
2011/08/08 PHP
Yii框架参数化查询中IN查询只能查询一个的解决方法
2017/05/20 PHP
PHP 应用容器化以及部署方法
2018/02/12 PHP
jquery和javascript中如何将一元素的内容赋给另一元素
2014/01/09 Javascript
javascript生成随机大小写字母的方法
2014/02/20 Javascript
AngularJS入门教程之学习环境搭建
2014/12/06 Javascript
javascript实现简单的贪吃蛇游戏
2015/03/31 Javascript
node.js调用C++开发的模块实例
2015/07/03 Javascript
快速学习jQuery插件 Cookie插件使用方法
2015/12/01 Javascript
基于Bootstrap实现tab标签切换效果
2020/04/15 Javascript
浅谈jQuery中的eq()与DOM中element.[]的区别
2016/10/28 Javascript
jQuery学习笔记——jqGrid的使用记录(实现分页、搜索功能)
2016/11/09 Javascript
jquery+ajax实现省市区三级联动效果简单示例
2017/01/04 Javascript
Angular.js组件之input mask对input输入进行格式化详解
2017/07/10 Javascript
Javascript防止图片拉伸的自适应处理方法
2017/12/26 Javascript
React事件处理的机制及原理
2018/12/03 Javascript
修改layui的后台模板的左侧导航栏可以伸缩的方法
2019/09/10 Javascript
package.json中homepage属性的作用详解
2020/03/11 Javascript
详谈Python2.6和Python3.0中对除法操作的异同
2017/04/28 Python
python中使用xlrd读excel使用xlwt写excel的实例代码
2018/01/31 Python
Django rest framework实现分页的示例
2018/05/24 Python
python-序列解包(对可迭代元素的快速取值方法)
2019/08/24 Python
python基于celery实现异步任务周期任务定时任务
2019/12/30 Python
python json 递归打印所有json子节点信息的例子
2020/02/27 Python
django序列化时使用外键的真实值操作
2020/07/15 Python
Python如何输出警告信息
2020/07/30 Python
25个CSS3动画按钮和菜单教程分享
2012/10/03 HTML / CSS
智能家居、吸尘器、滑板车、电动自行车网上购物:Geekmaxi
2021/01/18 全球购物
swtich是否能作用在byte上,是否能作用在long上,是否能作用在String上?
2013/03/30 面试题
员工培训邀请函
2014/01/11 职场文书
优秀交警事迹材料
2014/01/26 职场文书
利用Python第三方库实现预测NBA比赛结果
2021/06/21 Python
解析redis hash应用场景和常用命令
2021/08/04 Redis