只需要这一行代码就能让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 相关文章推荐
详解如何使用Python编写vim插件
Nov 28 Python
PyCharm 创建指定版本的 Django(超详图解教程)
Jun 18 Python
对Django 中request.get和request.post的区别详解
Aug 12 Python
Python3+Requests+Excel完整接口自动化测试框架的实现
Oct 11 Python
浅谈selenium如何应对网页内容需要鼠标滚动加载的问题
Mar 14 Python
Python退出时强制运行一段代码的实现方法
Apr 29 Python
基于PyTorch的permute和reshape/view的区别介绍
Jun 18 Python
解决TensorFlow程序无限制占用GPU的方法
Jun 30 Python
解决Windows下python和pip命令无法使用的问题
Aug 31 Python
Python程序慢的重要原因
Sep 04 Python
PyCharm上安装Package的实现(以pandas为例)
Sep 18 Python
python3爬虫中多线程的优势总结
Nov 24 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
php上传apk后自动提取apk包信息的使用(示例下载)
2013/04/26 PHP
PHP字符串word末字符实现大小写互换的方法
2014/11/10 PHP
详解js异步文件加载器
2016/01/24 PHP
mongodb和php的用法详解
2019/03/25 PHP
laravel框架模板之公共模板、继承、包含实现方法分析
2019/08/30 PHP
JavaScript格式化数字的函数代码
2010/11/30 Javascript
纯JS实现的批量图片预览加载功能
2011/08/14 Javascript
一个简单的jQuery插件ajaxfileupload.js实现ajax上传文件例子
2014/06/26 Javascript
使用不同的方法结合/合并两个JS数组
2014/09/18 Javascript
Javascript中使用parseInt函数需要注意的问题
2015/04/02 Javascript
jQuery实现鼠标经过事件的延时处理效果
2020/08/20 Javascript
BootStrap glyphicons 字体图标实现方法
2016/05/01 Javascript
最简单的tab切换实例代码
2016/05/13 Javascript
Javascript 调用 ActionScript 的简单方法
2016/09/22 Javascript
JS中闭包的经典用法小结(2则示例)
2016/12/28 Javascript
js弹出窗口简单实现代码
2017/03/22 Javascript
老生常谈js-react组件生命周期
2017/05/02 Javascript
JavaScript实现元素滚动条到达一定位置循环追加内容
2017/12/28 Javascript
vue页面切换到滚动页面显示顶部的实例
2018/03/13 Javascript
微信小程序http连接访问解决方案的示例
2018/11/05 Javascript
让mocha支持ES6模块的方法实现
2020/01/14 Javascript
[55:04]海涛DOTA2死魂复燃6.82版本介绍
2014/09/28 DOTA
深入源码解析Python中的对象与类型
2015/12/11 Python
python分批定量读取文件内容,输出到不同文件中的方法
2018/12/08 Python
很酷的python表白工具 你喜欢我吗
2019/04/11 Python
解决django后台样式丢失,css资源加载失败的问题
2019/06/11 Python
Python迭代器iterator生成器generator使用解析
2019/10/24 Python
pytorch中nn.Conv1d的用法详解
2019/12/31 Python
使用phonegap查找联系人的实现方法
2017/03/31 HTML / CSS
名人珠宝设计师:Melinda Maria Jewelry
2019/03/06 全球购物
如何估计一张表的大小(假设该表中有1万条数据)
2016/03/27 面试题
3的组成教学反思
2014/04/30 职场文书
写字楼租赁意向书
2014/07/30 职场文书
最美家庭活动方案
2014/08/31 职场文书
简单租房协议书(范本)
2014/10/13 职场文书
2014年政风行风自查自纠报告
2014/10/21 职场文书