详解如何利用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使用正则表达式匹配字符串开头并打印示例
Jan 11 Python
Django 生成登陆验证码代码分享
Dec 12 Python
python抓取网页中链接的静态图片
Jan 29 Python
Python爬虫包BeautifulSoup异常处理(二)
Jun 17 Python
python实现石头剪刀布程序
Jan 20 Python
Python Scrapy框架第一个入门程序示例
Feb 05 Python
Django操作session 的方法
Mar 09 Python
通过实例简单了解Python sys.argv[]使用方法
Aug 04 Python
Python如何实现Paramiko的二次封装
Jan 30 Python
Python tkinter实现日期选择器
Feb 22 Python
解决numpy数组互换两行及赋值的问题
Apr 17 Python
Python实现简单的俄罗斯方块游戏
Sep 25 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
虫族 Zerg 热键控制
2020/03/14 星际争霸
初学CAKEPHP 基础教程
2009/11/02 PHP
php 获取select下拉列表框的值
2010/05/08 PHP
PHP扩展程序实现守护进程
2015/04/16 PHP
showModalDialog 和 showModelessDialog
2007/01/22 Javascript
js 立即调用的函数表达式如何写
2014/01/12 Javascript
JavaScript 实现鼠标拖动元素实例代码
2014/02/24 Javascript
Js+php实现异步拖拽上传文件
2015/06/23 Javascript
js实现文本框只允许输入数字并限制数字大小的方法
2015/08/19 Javascript
js实现YouKu的漂亮搜索框效果
2015/08/19 Javascript
JS实现1000以内被3或5整除的数字之和
2016/02/18 Javascript
js 求时间差的实现代码
2016/04/26 Javascript
浅谈JavaScript 标准对象
2016/06/02 Javascript
Angularjs的ng-repeat中去除重复数据的方法
2016/08/05 Javascript
jQuery双向列表选择器select版
2016/11/01 Javascript
require、backbone等重构手机图片查看器
2016/11/17 Javascript
jquery的父、子、兄弟节点查找,节点的子节点循环方法
2016/12/07 Javascript
jQuery复合事件用法示例
2017/06/10 jQuery
JavaScript利用fetch实现异步请求的方法实例
2017/07/26 Javascript
js原生方法被覆盖,从新赋值原生的方法
2018/01/02 Javascript
vue使用$emit时,父组件无法监听到子组件的事件实例
2018/02/26 Javascript
JavaScript实现构造json数组的方法分析
2018/08/17 Javascript
[01:10]为家乡而战!完美世界城市挑战赛全国总决赛花絮
2019/07/25 DOTA
Python读写Excel文件的实例
2013/11/01 Python
python print 按逗号或空格分隔的方法
2018/05/02 Python
HTML5印章绘制电子签章图片(中文英文椭圆章、中文英文椭圆印章)
2019/06/03 HTML / CSS
国际象棋商店:The Chess Store
2018/07/09 全球购物
法学毕业生自我鉴定
2013/11/08 职场文书
学校消防安全制度
2014/01/30 职场文书
死亡证明书样本说明
2014/10/18 职场文书
2015年度物业公司工作总结
2015/04/27 职场文书
毕业论文致谢词
2015/05/14 职场文书
中小企业员工手册范本
2015/05/14 职场文书
小学生暑假生活总结
2015/07/13 职场文书
初中英语教学反思范文
2016/02/15 职场文书
Windows 64位 安装 mysql 8.0.28 图文教程
2022/04/19 MySQL