详解如何利用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 执行字符串表达式函数(eval exec execfile)
Aug 11 Python
通过C++学习Python
Jan 20 Python
Python发送以整个文件夹的内容为附件的邮件的教程
May 06 Python
Python的Flask框架中的Jinja2模板引擎学习教程
Jun 30 Python
Python自动化测试Eclipse+Pydev 搭建开发环境
Aug 15 Python
pandas按若干个列的组合条件筛选数据的方法
Apr 11 Python
Python利用sqlacodegen自动生成ORM实体类示例
Jun 04 Python
python 定时器每天就执行一次的实现代码
Aug 14 Python
如何用Python来理一理红楼梦里的那些关系
Aug 14 Python
python实现多进程按序号批量修改文件名的方法示例
Dec 30 Python
谈谈Python:为什么类中的私有属性可以在外部赋值并访问
Mar 05 Python
matplotlib交互式数据光标实现(mplcursors)
Jan 13 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教程 基本语法
2009/10/23 PHP
php查找任何页面上的所有链接的方法
2013/12/03 PHP
使用PHP处理数据库数据如何将数据返回客户端并显示当前状态
2016/02/16 PHP
yii2使用gridView实现下拉列表筛选数据
2017/04/10 PHP
CodeMirror2 IE7/IE8 下面未知运行时错误的解决方法
2012/03/29 Javascript
JS实现仿百度输入框自动匹配功能的示例代码
2014/02/19 Javascript
js转化毫秒为时间格式代码
2014/04/10 Javascript
node.js中的http.response.removeHeader方法使用说明
2014/12/14 Javascript
jQuery判断多个input file 都不能为空的例子
2015/06/23 Javascript
jQuery实现仿腾讯迷你首页选项卡效果代码
2015/09/17 Javascript
Vue中util的工具函数实例详解
2019/07/08 Javascript
layui 实现表单和文件上传一起传到后台的例子
2019/09/16 Javascript
微信小程序点击生成朋友圈分享图(遇到的坑)
2020/06/17 Javascript
[02:09]抵达西雅图!中国军团加油!
2014/07/07 DOTA
讲解Python中的标识运算符
2015/05/14 Python
详解Python中的条件判断语句
2015/05/14 Python
利用Python中unittest实现简单的单元测试实例详解
2017/01/09 Python
Python获取当前脚本文件夹(Script)的绝对路径方法代码
2019/08/27 Python
python3实现绘制二维点图
2019/12/04 Python
用openCV和Python 实现图片对比,并标识出不同点的方式
2019/12/19 Python
给keras层命名,并提取中间层输出值,保存到文档的实例
2020/05/23 Python
用python对excel查重
2020/12/07 Python
Python项目打包成二进制的方法
2020/12/30 Python
python实现经典排序算法的示例代码
2021/02/07 Python
ALDI奥乐齐官方海外旗舰店:德国百年超市
2017/12/27 全球购物
FLIR美国官网:热成像, 夜视和红外摄像系统
2018/07/13 全球购物
Strawberrynet草莓网新加坡站:护肤、彩妆、香水及美发产品
2018/08/31 全球购物
Pop In A Box英国:Funko POP搪胶公仔
2019/05/27 全球购物
JDO的含义
2012/11/17 面试题
求职信需要的五点内容
2014/02/01 职场文书
交通事故委托书范本精选
2014/10/04 职场文书
大学生个人简历自荐信
2015/03/06 职场文书
就业推荐表院系意见
2015/06/05 职场文书
全民创业工作总结
2015/08/13 职场文书
mysql数据库隔离级别详解
2022/06/16 MySQL
Beekeeper Studio开源数据库管理工具比Navicat更炫酷
2022/06/21 数据库