详解如何利用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 list转dict示例分享
Jan 28 Python
Python实现分割文件及合并文件的方法
Jul 10 Python
Python 列表(List) 的三种遍历方法实例 详解
Apr 15 Python
python的paramiko模块实现远程控制和传输示例
Oct 13 Python
Python设计模式之命令模式简单示例
Jan 10 Python
Python编程在flask中模拟进行Restful的CRUD操作
Dec 28 Python
Django如何自定义model创建数据库索引的顺序
Jun 20 Python
布隆过滤器的概述及Python实现方法
Dec 08 Python
opencv3/C++图像像素操作详解
Dec 10 Python
Python使用pycharm导入pymysql教程
Sep 16 Python
浅析python字符串前加r、f、u、l 的区别
Jan 24 Python
Python Django项目和应用的创建详解
Nov 27 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 查找字符串常用函数介绍
2012/06/07 PHP
使用PHP函数scandir排除特定目录
2014/06/12 PHP
php strftime函数获取日期时间(switch用法)
2018/05/16 PHP
简单的JS多重继承示例
2008/03/13 Javascript
Node.js重新刷新session过期时间的方法
2016/02/04 Javascript
原生JavaScript编写canvas版的连连看游戏
2016/05/29 Javascript
jQuery Easyui使用(二)之可折叠面板动态加载无效果的解决方法
2016/08/17 Javascript
js中利用cookie实现记住密码功能
2020/08/20 Javascript
BootStrap Datepicker 插件修改为默认中文的实现方法
2017/02/10 Javascript
NodeJS自定义模块写法(详解)
2017/06/27 NodeJs
vue-cli 组件的导入与使用教程详解
2018/04/11 Javascript
JS获取指定月份的天数两种实现方法
2018/06/22 Javascript
AngularJS实现的自定义过滤器简单示例
2019/02/02 Javascript
vue动态绘制四分之三圆环图效果
2019/09/03 Javascript
node.js开发辅助工具nodemon安装与配置详解
2020/02/06 Javascript
python服务器端收发请求的实现代码
2014/09/29 Python
Python中列表的一些基本操作知识汇总
2015/05/20 Python
Python搜索引擎实现原理和方法
2017/11/27 Python
python 3.5实现检测路由器流量并写入txt的方法实例
2017/12/17 Python
python3+mysql查询数据并通过邮件群发excel附件
2018/02/24 Python
vue.js实现输入框输入值内容实时响应变化示例
2018/07/07 Python
使用ITK-SNAP进行抠图操作并保存mask的实例
2020/07/01 Python
Django crontab定时任务模块操作方法解析
2020/09/10 Python
html5实现的便签特效(实战分享)
2013/11/29 HTML / CSS
法国二手手袋、手表和奢侈珠宝购物网站:Collector Square
2018/07/05 全球购物
武汉世纪畅想数字传播有限公司 .NET笔试题
2015/06/13 面试题
PHP引擎php.ini参数优化深入讲解
2021/03/24 PHP
网上签名寄语活动留言
2014/01/18 职场文书
父亲的菜园教学反思
2014/02/13 职场文书
幼儿园小班评语
2014/04/18 职场文书
2014年国庆节演讲稿
2014/09/02 职场文书
科技活动周标语
2014/10/08 职场文书
债务追讨授权委托书范本
2014/10/16 职场文书
文体活动总结
2015/02/04 职场文书
大一新生军训新闻稿
2015/07/17 职场文书
《秋思》教学反思
2016/02/23 职场文书