详解如何利用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 uuid模块使用实例
Apr 08 Python
15行Python代码带你轻松理解令牌桶算法
Mar 21 Python
关于Django ForeignKey 反向查询中filter和_set的效率对比详解
Dec 15 Python
python使用Plotly绘图工具绘制散点图、线形图
Apr 02 Python
Python异常处理例题整理
Jul 07 Python
基于python实现学生信息管理系统
Nov 22 Python
pytorch 获取tensor维度信息示例
Jan 03 Python
解决import tensorflow as tf 出错的原因
Apr 16 Python
python3发送request请求及查看返回结果实例
Apr 30 Python
Keras SGD 随机梯度下降优化器参数设置方式
Jun 19 Python
python中xlrd模块的使用详解
Feb 01 Python
python如何查找列表中元素的位置
May 30 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/09/28 PHP
在PHP中检查PHP文件是否有语法错误的方法
2009/12/23 PHP
PHPMailer 中文使用说明小结
2010/01/22 PHP
递归删除一个节点以及该节点下的所有节点示例
2014/03/19 PHP
PHP文件锁定写入实例解析
2014/07/14 PHP
javascript 事件查询综合 推荐收藏
2010/03/10 Javascript
setTimeout的延时为0时多个浏览器的区别
2012/05/23 Javascript
JQuery的read函数与js的onload不同方式实现
2013/03/18 Javascript
js Math 对象的方法
2013/09/01 Javascript
JS for...in 遍历语句用法实例分析
2016/08/24 Javascript
AngularJS学习笔记(三)数据双向绑定的简单实例
2016/11/08 Javascript
js中创建对象的几种方式
2017/02/05 Javascript
微信小程序 scroll-view实现锚点滑动的示例
2017/12/06 Javascript
使用vue-router beforEach实现判断用户登录跳转路由筛选功能
2018/06/25 Javascript
JS通过识别id、value值对checkbox设置选中状态
2020/02/19 Javascript
Vue实现点击箭头上下移动效果
2020/06/11 Javascript
[02:08]DOTA2英雄基础教程 马格纳斯
2014/01/17 DOTA
Python实现简单拆分PDF文件的方法
2015/07/30 Python
python中实现k-means聚类算法详解
2017/11/11 Python
python实现自动发送邮件
2018/06/20 Python
OpenCV+Python3.5 简易手势识别的实现
2020/12/21 Python
详解python3类型注释annotations实用案例
2021/01/20 Python
不同浏览器对CSS3和HTML5的支持状况
2009/10/31 HTML / CSS
使用HTML5的Notification API制作web通知的教程
2015/05/08 HTML / CSS
HMV日本官网:全球知名的音乐、DVD和电脑游戏零售巨头
2016/08/13 全球购物
Habitat家居英国官方网站:沙发、家具、照明、厨房和户外
2019/12/12 全球购物
澳大利亚购买太阳镜和眼镜网站:Glamoureyes
2020/09/22 全球购物
上班上网检讨书
2014/01/29 职场文书
2014年度思想工作总结
2014/11/27 职场文书
2015年度党风廉政建设工作情况汇报
2015/01/02 职场文书
婚庆司仪开场白
2015/05/29 职场文书
浅谈redis五大数据结构和使用场景
2021/04/12 Redis
MySQL数字类型自增的坑
2021/05/07 MySQL
python使用pywinauto驱动微信客户端实现公众号爬虫
2021/05/19 Python
Python Pygame实战之塔防游戏的实现
2022/03/17 Python
OpenCV项目实践之停车场车位实时检测
2022/04/11 Python