详解如何利用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爬取NUS-WIDE数据库图片
Oct 05 Python
Python reduce()函数的用法小结
Nov 15 Python
python装饰器-限制函数调用次数的方法(10s调用一次)
Apr 21 Python
python 按照固定长度分割字符串的方法小结
Apr 30 Python
Python matplotlib的使用并自定义colormap的方法
Dec 13 Python
python消费kafka数据批量插入到es的方法
Dec 27 Python
python实现合并两个排序的链表
Mar 03 Python
PyQt5实现简单数据标注工具
Mar 18 Python
基于Numpy.convolve使用Python实现滑动平均滤波的思路详解
May 16 Python
python实现画循环圆
Nov 23 Python
浅谈Tensorflow 动态双向RNN的输出问题
Jan 20 Python
PyCharm vs VSCode,作为python开发者,你更倾向哪种IDE呢?
Aug 17 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
关于JSON以及JSON在PHP中的应用技巧
2013/11/27 PHP
smarty中英文多编码字符截取乱码问题解决方法
2014/10/28 PHP
Laravel 默认邮箱登录改成用户名登录的实现方法
2019/08/12 PHP
php服务器的系统详解
2019/10/12 PHP
解决Extjs 4 Panel作为Window组件的子组件时出现双重边框问题
2013/01/11 Javascript
javascript实现数字验证码的简单实例
2014/02/10 Javascript
使用upstart把nodejs应用封装为系统服务实例
2014/06/01 NodeJs
javascript中var的重要性分析
2015/02/11 Javascript
js实现字符串和数组之间相互转换操作
2016/01/12 Javascript
Javascript生成全局唯一标识符(GUID,UUID)的方法
2016/02/27 Javascript
详解Chart.js轻量级图表库的使用经验
2018/05/22 Javascript
详解mpvue scroll-view自动回弹bug解决方案
2018/10/01 Javascript
一文搞懂ES6中的Map和Set
2019/05/20 Javascript
WEEX环境搭建与入门详解
2019/10/16 Javascript
JS基础之逻辑结构与循环操作示例
2020/01/19 Javascript
django接入新浪微博OAuth的方法
2015/06/29 Python
在Python中定义和使用抽象类的方法
2016/06/30 Python
Python实现购物车购物小程序
2018/04/18 Python
python在回调函数中获取返回值的方法
2019/02/22 Python
python range实例用法分享
2020/02/06 Python
Tensorflow 使用pb文件保存(恢复)模型计算图和参数实例详解
2020/02/11 Python
python网络编程socket实现服务端、客户端操作详解
2020/03/24 Python
python代码如何注释
2020/06/01 Python
Python-for循环的内部机制
2020/06/12 Python
Python 通过正则表达式快速获取电影的下载地址
2020/08/17 Python
Anaconda+spyder+pycharm的pytorch配置详解(GPU)
2020/10/18 Python
Python tkinter实现日期选择器
2021/02/22 Python
护理学专业推荐信
2013/12/03 职场文书
大学生职业生涯规划书的基本内容
2014/01/06 职场文书
咖啡书吧创业计划书
2014/01/13 职场文书
销售员岗位职责范本
2014/02/03 职场文书
房产继承公证书
2014/04/09 职场文书
2014年大学生党员自我评议
2014/09/22 职场文书
基层党员对照检查材料
2014/09/24 职场文书
管理者日常工作必备:22条企业管理流程模板!
2019/07/12 职场文书
Ruby序列化和持久化存储 Marshal和Pstore介绍
2022/04/18 Ruby