详解如何利用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编程判断一个正整数是否为素数的方法
Apr 14 Python
python实现简单聊天应用 python群聊和点对点均实现
Sep 14 Python
一百多行python代码实现抢票助手
Sep 25 Python
Python使用sqlalchemy模块连接数据库操作示例
Mar 13 Python
python函数不定长参数使用方法解析
Dec 14 Python
python 图像的离散傅立叶变换实例
Jan 02 Python
python 线性回归分析模型检验标准--拟合优度详解
Feb 24 Python
Keras load_model 导入错误的解决方式
Jun 09 Python
Python实现简单的猜单词小游戏
Oct 28 Python
python实现ping命令小程序
Dec 28 Python
基于Python实现天天酷跑功能
Jan 06 Python
Python基础之教你怎么在M1系统上使用pandas
May 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
腾讯QQ php程序员面试题目整理
2010/06/08 PHP
解决phpmyadmin中缺少mysqli扩展问题的方法
2013/05/06 PHP
浅谈PHP与C#的值类型指向区别的详解
2013/05/21 PHP
Laravel Validator自定义错误返回提示消息并在前端展示
2019/05/09 PHP
PHP中__set()实例用法和基础讲解
2019/07/23 PHP
Dojo 学习要点
2010/09/03 Javascript
jQuery Ajax方法调用 Asp.Net WebService 的详细实例代码
2011/04/27 Javascript
jQuery EasyUI API 中文文档 - TreeGrid 树表格使用介绍
2011/11/21 Javascript
jquery模拟SELECT下拉框取值效果
2013/10/23 Javascript
jquery与prototype框架的详细对比
2013/11/21 Javascript
javascript 回到顶部效果的实现代码
2014/02/17 Javascript
javascript 闭包详解
2015/02/15 Javascript
在Ubuntu系统上安装Ghost博客平台的教程
2015/06/17 Javascript
JS控制伪元素的方法汇总
2016/04/06 Javascript
微信小程序开发探究
2016/12/27 Javascript
jQuery实现动态文字搜索功能
2017/01/05 Javascript
基于vue-cli配置lib-flexible + rem实现移动端自适应
2017/12/26 Javascript
前后端如何实现登录token拦截校验详解
2018/09/03 Javascript
js实现跟随鼠标移动的小球
2019/08/26 Javascript
vue 遮罩层阻止默认滚动事件操作
2020/07/28 Javascript
[04:21]狐狸妈带你到现场 DOTA2 TI中国区预选赛线下赛路线指引
2014/05/22 DOTA
[01:08:48]LGD vs OG 2018国际邀请赛淘汰赛BO3 第三场 8.25
2018/08/29 DOTA
华为校园招聘上机笔试题 扑克牌大小(python)
2020/04/22 Python
浅谈Python3实现两个矩形的交并比(IoU)
2020/01/18 Python
Pandas中两个dataframe的交集和差集的示例代码
2020/12/13 Python
找到您丢失的钥匙、钱包和手机:Tile
2017/05/19 全球购物
MYSQL基础面试题
2012/05/13 面试题
毕业生自荐书模版
2014/01/04 职场文书
活动总结模板
2014/05/09 职场文书
年底个人总结范文
2015/03/10 职场文书
辣妈辣妹观后感
2015/06/10 职场文书
2015年教师节新闻稿
2015/07/17 职场文书
基层医务人员三严三实心得体会
2016/01/05 职场文书
2017寒假社会实践心得体会范文
2016/01/14 职场文书
导游词之寿县报恩寺
2020/01/19 职场文书
Python使用MapReduce进行简单的销售统计
2022/04/22 Python