只需要这一行代码就能让python计算速度提高十倍


Posted in Python onMay 24, 2021

一、前言

Python语言近年来人气爆棚。它广泛应用于数据科学,人工智能,以及网络安全问题中,由于代码可读性较强,学习效率较高,吸引了许多非科班的同学进行学习。然而,使用Python一段时间以后,发现它在速度上完全没有优势可言,特别是计算密集型任务里,性能问题一直是Python的软肋。本文主要介绍了Python的JIT编译器Numba,能够在对代码侵入最少的情况下,极大加速计算核心函数的运行速度,适合数据分析业务相关的同学使用。

首先要回答这样一个问题:当运行同一个程序时,为什么Python会 比其他语言慢2到10倍?为什么我们无法将它变得更快?

以下是最主要的原因:

  • “它是GIL(Global Interpreter Lock全局解释器锁)”
  • “它是解释型语言而非编译语言”
  • “它是动态类型语言

由于本文的着重点并不是解释Python速度慢的原因以及背后的逻辑,这部分就不深入探讨了,欢迎有兴趣的同学自行搜索?

二、Python的JIT编译器

为了兼具移植性和性能,聪明的工程师们发明了 JIT 这个东西,所谓的 JIT 就是说在解释型语言中,对于经常用到的或者说有较大性能提升的代码在解释的时候编译成机器码,其他一次性或者说没有太大性能提升的代码还是以字节码的方式执行。这样的话,就能在保证移植性的同时,又能让性能提升一大截,

JIT编译在代码运行时动态将Python代码编译为机器代码执行,由于避免了Python内置的解释器,运行速度会有很大提升。比较流行的JIT方案是Numba和Pypy,但由于Python的历史包袱和语法变化等原因,没有一个能够完美实现的方案。方案各自存在不同的优缺点,需要在根据使用领域选择合适的方案。

  • Pypy支持全局的加速,但对C库支持不好,较为适合用于Web服务等事务型任务。
  • Numba能够对某些函数和库进行加速,高性能的同时保持了Python的兼容性,但使用的范围会受到一定限制。

只需要这一行代码就能让python计算速度提高十倍 

三、Numba快速学习

我们主要介绍Numba的基本用法,能够在对代码侵入最少的情况下,极大加速计算核心函数的运行速度,适合数据分析业务相关的同学使用。

Numba通过使用LLVM技术,将Python代码编译生成优化后的机器码,可以大幅提高代码执行效率。

对于Numba的学习,纽约大学提供了一套入门级别的视频,代码简单,纽约大学Numba快速学习,如果想要浏览中文文章欢迎继续往下看!

关于安装

首先是安装numba,根据python环境,运行不同的安装命令:

conda install numba
pip install numba

四、关于使用

一句话总结:使用Numba最简单的方式就是在函数定义前加@jit 或 @njit的装饰即可。

Numba通过在函数定义前加decorator(修饰符)来申明是否进行加速。如上文所说,最简单的使用方法是@jit。对于Numba的@jit有两种编译模式:nopython和object模式。

nopython模式会完全编译这个被修饰的函数,函数的运行与Python解释器完全无关,不会调用Python的C语言API。如果想获得最佳性能,推荐使用此种模式。同时由于@jit(nopython=True)太常用了,Numba提供了@njit修饰符,和这句话等价,方便使用。但这种模式要求函数中所有变量的类型都可以被编译器推导(一些基本类型,如不能是一些库或自己定义的数据类型等),否则就会报错。

object模式中编译器会自动识别函数中循环语句等可以编译加速的代码部分,并编译成机器码,对于剩下不能识别的部分交给Python解释器运行。如果想获取最佳性能,避免使用这种方法(For best performance avoid using this mode!)。

如果没设置参数nopython=True,Numba首先会尝试使用nopython模式,如果因为某些原因无法使用,则会使用object模式。加了nopython后则会强制编译器使用nopython模式,但如果代码出现了不能自动推导的类型,有报错的风险。

五、实验提升

from numba import jit
import random, time

def monte_carlo_pi(sam):
    account = 0
    for i in range(sam):
        x = random.random()
        y = random.random()
        if (x ** 2 + y ** 2) < 1.0:
            account += 1
    return 4.0 * account / sam

@jit
def jit_monte_carlo_pi(sam):
    account = 0
    for i in range(sam):
        x = random.random()
        y = random.random()
        if (x ** 2 + y ** 2) < 1.0:
            account += 1
    return 4.0 * account / sam

loops = [100000, 1000000, 10000000, 100000000, 1000000000]

for loop in loops:
	startTime = time.time()
	monte_carlo_pi(loop)
	t = time.time() - startTime
	print('python {} loop: {}'.format(loop, t))

	startTime = time.time()
	jit_monte_carlo_pi(loop)
	t = time.time() - startTime
	print('numba {} loop: {}'.format(loop, t))

对于以上代码,运行的结果是:
python 100000    loop: 0.0469999313354
numba  100000    loop: 0.213999986649
python 1000000   loop: 0.478999853134
numba  1000000   loop: 0.0110001564026
python 10000000  loop: 4.82499980927
numba  10000000  loop: 0.107000112534
python 100000000 loop: 48.728000164
numba  100000000 loop: 1.05900001526
python 1000000000 loop: 489.142100134
numba  1000000000 loop: 11.01402001452

可以看到,jit编译后有约47倍的提升。循环次数越多,numba的加速效果就越明显。对于更复杂的计算函数,numba可能会有更好的效果。

到此这篇关于只需要这一行代码就能让python计算速度提高十倍的文章就介绍到这了,更多相关提高python计算速度内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Python 相关文章推荐
基于Linux系统中python matplotlib画图的中文显示问题的解决方法
Jun 15 Python
python下载文件记录黑名单的实现代码
Oct 24 Python
python实现协同过滤推荐算法完整代码示例
Dec 15 Python
详解Python中的正则表达式
Jul 08 Python
解决python3 urllib 链接中有中文的问题
Jul 16 Python
python中的常量和变量代码详解
Jul 25 Python
pandas求两个表格不相交的集合方法
Dec 08 Python
详解Python打包分发工具setuptools
Aug 05 Python
使用python-opencv读取视频,计算视频总帧数及FPS的实现
Dec 10 Python
使用Python给头像加上圣诞帽或圣诞老人小图标附源码
Dec 25 Python
解决ROC曲线画出来只有一个点的问题
Feb 28 Python
Python 操作pdf pdfplumber读取PDF写入Exce
Aug 14 Python
pytorch 如何使用float64训练
pytorch 使用半精度模型部署的操作
May 24 #Python
解决Pytorch半精度浮点型网络训练的问题
May 24 #Python
Python办公自动化之Excel(中)
May 24 #Python
PyTorch梯度裁剪避免训练loss nan的操作
May 24 #Python
python3读取文件指定行的三种方法
May 24 #Python
pytorch中Schedule与warmup_steps的用法说明
May 24 #Python
You might like
kohana框架上传文件验证规则写法示例
2014/07/14 PHP
php中socket通信机制实例详解
2015/01/03 PHP
微信公众平台开发之配置与请求
2015/08/26 PHP
jQuery实现的类flash菜单效果代码
2010/05/17 Javascript
js 多种变量定义(对象直接量,数组直接量和函数直接量)
2010/05/24 Javascript
JavaScript常用小技巧小结
2014/12/29 Javascript
NodeJS学习笔记之Connect中间件模块(一)
2015/01/27 NodeJs
JS实现浏览器状态栏显示时间的方法
2015/10/27 Javascript
jQuery实现二级下拉菜单效果
2016/01/05 Javascript
基于JavaScript实现智能右键菜单
2016/03/02 Javascript
JavaScript生成带有缩进的表格代码
2016/06/15 Javascript
微信小程序前端源码逻辑和工作流
2016/09/25 Javascript
浅谈js中的变量名和函数名重名
2017/02/13 Javascript
原生JS实现隐藏显示图片 JS实现点击切换图片效果
2021/01/27 Javascript
利用VS Code开发你的第一个AngularJS 2应用程序
2017/12/15 Javascript
基于React+Redux的SSR实现方法
2018/07/03 Javascript
vue-cli2打包前和打包后的css前缀不一致的问题解决
2018/08/24 Javascript
微信小程序实现分页加载效果
2020/11/19 Javascript
[43:57]Liquid vs Mineski 2019国际邀请赛小组赛 BO2 第二场 8.16
2019/08/19 DOTA
python编程实现12306的一个小爬虫实例
2017/12/27 Python
详解Python 实现元胞自动机中的生命游戏(Game of life)
2018/01/27 Python
使用python将请求的requests headers参数格式化方法
2019/01/02 Python
Python树莓派学习笔记之UDP传输视频帧操作详解
2019/11/15 Python
Python测试Kafka集群(pykafka)实例
2019/12/23 Python
利用Python脚本批量生成SQL语句
2020/03/04 Python
Keras构建神经网络踩坑(解决model.predict预测值全为0.0的问题)
2020/07/07 Python
python pygame 愤怒的小鸟游戏示例代码
2021/02/25 Python
全方位了解CSS3的Regions扩展
2015/08/07 HTML / CSS
用CSS3和table标签实现一个圆形轨迹的动画的示例代码
2019/01/17 HTML / CSS
美国家居装饰网上商店:Lulu & Georgia
2019/09/14 全球购物
酒店个人求职信范文
2014/01/25 职场文书
房产代理公证处委托书
2014/04/04 职场文书
党校培训自我鉴定范文
2014/04/10 职场文书
餐饮商业计划书范文
2014/04/29 职场文书
中国古代史学名著《战国策》概述
2019/08/09 职场文书
一篇带你入门Java垃圾回收器
2021/06/16 Java/Android