详解如何利用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中使用hashlib模块处理算法的教程
Apr 28 Python
Python模拟登录验证码(代码简单)
Feb 06 Python
基于使用paramiko执行远程linux主机命令(详解)
Oct 16 Python
Python3中在Anaconda环境下安装basemap包
Oct 21 Python
pycharm打开命令行或Terminal的方法
Jan 16 Python
使用Python的SymPy库解决数学运算问题的方法
Mar 27 Python
Python实现简单的列表冒泡排序和反转列表操作示例
Jul 10 Python
如何分离django中的媒体、静态文件和网页
Nov 12 Python
Python-openCV读RGB通道图实例
Jan 17 Python
Python中zipfile压缩文件模块的基本使用教程
Jun 14 Python
Python面向对象特殊属性及方法解析
Sep 16 Python
python图像处理基本操作总结(PIL库、Matplotlib及Numpy)
Jun 08 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下载excel无法打开的解决方法
2013/12/24 PHP
php使用正则过滤js脚本代码实例
2014/05/10 PHP
理解PHP中的Session及对Session有效期的控制
2016/01/08 PHP
PHP之图片上传类实例代码(加了缩略图)
2016/06/30 PHP
php将文件夹打包成zip文件的简单实现方法
2016/10/04 PHP
一文看懂PHP进程管理器php-fpm
2020/06/01 PHP
js innerHTML 的一些问题的解决方法
2008/06/22 Javascript
JAVASCRIPT车架号识别/验证函数代码 汽车车架号验证程序
2012/01/08 Javascript
Jquery跨浏览器文本复制插件Zero Clipboard的使用方法
2016/02/28 Javascript
学习Bootstrap滚动监听 附调用方法
2016/07/02 Javascript
js改变透明度实现轮播图的算法
2020/08/24 Javascript
Node.js使用Angular简单示例
2018/05/11 Javascript
JS实现同一DOM元素上onClick事件与onDblClick事件并存的解决方法
2018/06/07 Javascript
详解ES7 Decorator 入门解析
2019/02/18 Javascript
js获取form表单中name属性的值
2019/02/27 Javascript
react 生命周期实例分析
2020/05/18 Javascript
浅谈js数组splice删除某个元素爬坑
2020/10/14 Javascript
[49:27]2018DOTA2亚洲邀请赛 4.4 淘汰赛 TNC vs VG 第一场
2018/04/05 DOTA
python使用htmllib分析网页内容的方法
2015/05/08 Python
pyqt5简介及安装方法介绍
2018/01/31 Python
TensorFlow saver指定变量的存取
2018/03/10 Python
Python 占位符的使用方法详解
2019/07/10 Python
python 抓包保存为pcap文件并解析的实例
2019/07/23 Python
python3多线程知识点总结
2019/09/26 Python
浅谈python量化 双均线策略(金叉死叉)
2020/06/03 Python
Python之京东商品秒杀的实现示例
2021/01/06 Python
CSS3实现的炫酷菜单代码分享
2015/03/12 HTML / CSS
苹果中国官方网站:Apple中国
2016/07/22 全球购物
高中生学习总结的自我评价范文
2013/10/13 职场文书
护理专业应届毕业生推荐信
2013/11/15 职场文书
店长助理岗位职责
2013/12/13 职场文书
中国央视网签名寄语
2014/01/18 职场文书
党员干部廉洁自律承诺书
2015/04/28 职场文书
七年级英语教学反思
2016/02/15 职场文书
MySQL Router的安装部署
2021/04/24 MySQL
Golang数据类型和相互转换
2022/04/12 Golang