Python代码加速
主要考虑代码优化加速,而非代码逻辑优化。

Python代码直接运行GPU是不行的,需要一定的改变,Numba是一个接口,不过本文主要针对CPU下的Python代码加速。

Python解释器工作原理
Python文件执行过程

.py文件通过解释器转化为虚拟机可以执行的字节码(.pyc);
字节码在虚拟机上执行,得到结果;
字节码是一种只能运行在虚拟机上的文件,默认后缀.pyc,Python生成.pyc之后一般放在内存中继续使用,并不是每次都将.pyc文件保存到磁盘上。

虚拟机是基于硬件和操作系统的。

.pyc字节码通过Python虚拟机与硬件交互,就是说虚拟机的存在导致程序与硬件之间增加了中间层。效率自然被拖后。

JIT(Just-In-Time)
JIT技术中,JIT编译器将Python源代码.py直接编译成机器可以执行的机器语言(机器码),就可以直接在CPU等硬件上运行。

这样,JIT就跳过了原来的虚拟机,执行速度几乎与用C语言编程速度无差别。

Numba库
Numba是Anaconda公司开发的针对Python的开源JIT编译器,用于提供Python版CPU和GPU编程,速度比原生Python快数十倍。一、安装Numba
pip install numba
# 或者
conda install numba

二、使用方法:装饰器

from numba import jit
import numpy as npSIZE = 2000
x = np.random.random((SIZE, SIZE))
"""
给定n*n矩阵,对矩阵每个元素计算tanh值,然后求和。
因为要循环矩阵中的每个元素,计算复杂度为 n*n。
"""
@jit # numba的使用方法
def jit_tan_sum(a):   # 函数在被调用时编译成机器语言tan_sum = 0for i in range(SIZE):   # Numba 支持循环for j in range(SIZE):tan_sum += np.tanh(a[i, j])   # Numba 支持绝大多数NumPy函数return tan_sumprint(jit_tan_sum(x))

如代码所示,只是在函数上加一个装饰器@jit,就可以将运行速度提升20多倍。

@jit装饰器的本质,是将函数编译为机器码,省掉虚拟机环节,提升速度。

三、Numba的使用场景总结
numba目前只支持Python原生函数和部分Numpy函数,其他场景下无效。

from numba import jit
import pandas as pdx = {'a': [1, 2, 3], 'b': [20, 30, 40]}@jit
def use_pandas(a): # Function will not benefit from Numba jitdf = pd.DataFrame.from_dict(a) # Numba doesn't know about pd.DataFramedf += 1                        # Numba doesn't understand what this isreturn df.cov()                # or this!print(use_pandas(x))

上述代码中使用了Pandas,而Pandas并不是原生代码,而是更高层次的封装,Numba不能理解pandas内部在做什么,所以无法对其加速。

而一些常用的机器学习框架,比如scikit-learn, tensorflow, pyrorch等,已经做了大量的优化,不适合再使用Numba做加速。

可以简单总结为,Numba不支持:

pandas
scikit-learn, tensorflow, pyrorch
try…except 异常处理
with 语句
yield from
四、Numba具体使用过程

Numba有两种模式:

@jit:object模式:上图左侧
Numba的@jit装饰器会尝试优化代码,如果发现不支持(比如pandas等),那么Numba会继续使用Python原来的方法去执行该函数。

@jit(nopython=True)或者@njit:nopython模式:上图右侧
强制加速,不会进入上图左侧流程,只进行右侧流程,如果编译不成功,就抛出异常。

实际使用中,一把推荐将代码中计算密集的部分作为单独的函数提出来,并使用nopython方法优化,这样可以保证能用到Numba加速;其余部分还是使用Python原生代码。

五、编译开销
编译源代码需要一定的时间:

C/C++等编译型语言是提前把整个程序先编译好,再执行可执行文件;
Numba库是懒编译(Lazy Compilation)技术;
其中,懒编译技术(Lazy Compilation)即

在运行过程中第一次发现源代码中有@jit,才将该代码块编译;
同一个Numba函数多次调用,只需要编译一次;
总 时 间 = 编 译 时 间 + 运 行 时 间 总时间=编译时间+运行时间
总时间=编译时间+运行时间

from numba import jit
import numpy as np
import timeSIZE = 2000
x = np.random.random((SIZE, SIZE))"""
给定n*n矩阵,对矩阵每个元素计算tanh值,然后求和。
因为要循环矩阵中的每个元素,计算复杂度为 n*n。
"""
@jit
def jit_tan_sum(a):   # 函数在被调用时编译成机器语言tan_sum = 0for i in range(SIZE):   # Numba 支持循环for j in range(SIZE):tan_sum += np.tanh(a[i, j])   # Numba 支持绝大多数NumPy函数return tan_sum# 总时间 = 编译时间 + 运行时间
start = time.time()
jit_tan_sum(x)
end = time.time()
print("Elapsed (with compilation) = %s" % (end - start))# Numba将加速的代码缓存下来
# 总时间 = 运行时间
start = time.time()
jit_tan_sum(x)
end = time.time()
print("Elapsed (after compilation) = %s" % (end - start))

上述代码中,两次调用了Numba优化函数,第一次执行时需要编译,第二次就直接使用缓存的已经编译好的代码,运行时间大大缩短。

六、确定输入输出类型Eager Compilation:节省编译速度
原生Python速度慢的另一个因素是变量类型不确定,Python解释器需要进行大量的类型推断。

Numba也要推断输入输出的类型:

from numba import jit, int32

@jit("int32(int32, int32)", nopython=True)
def f2(x, y):
    # A somewhat trivial example
    return x + y

@jit(int32(int32, int32))告知Numba你的函数在使用什么样的输入和输出:

括号内是输入;
括号左侧是输出;
这样不会加快执行速度,但是会加快编译速度,可以更快将函数编译到机器码上。

Numba原理

Numba使用了LLVM和NVVM技术,此技术将Python等解释型语言直接翻译成CPU、GPU可执行的机器码。

Python Numba CPU下加速相关推荐

  1. Python Numba实现GPU加速

    Python与GPU Python作为解释型语言,.py文件一般是没法直接用GPU加速的,关于Python与GPU的结合点,以及GPU.CPU.CUDA.多核.并行.机器码-等底层实现,参考: < ...

  2. python: numba 加速python的 for loop

    一.背景 写了个算法 需要多次计算两个字符串的编辑距离.这部分耗时比较多,想要进行优化.编辑距离代码见最后的附录.编辑距离本质上是双层for loop,而且是有依赖关系的for loop,因此无法并行 ...

  3. python GIL 全局锁,多核cpu下的多线程性能究竟如何?

    python GIL 全局锁,多核cpu下的多线程性能究竟如何?GIL全称Global Interpreter Lock GIL是什么? 首先需要明确的一点是GIL并不是Python的特性,它是在实现 ...

  4. 在英特尔 CPU 上加速 Stable Diffusion 推理

    点击蓝字 关注我们,让开发变得更有趣 前一段时间,我们向大家介绍了最新一代的 英特尔至强 CPU (代号 Sapphire Rapids),包括其用于加速深度学习的新硬件特性,以及如何使用它们来加速自 ...

  5. win7+vs2015/13+caffe+matlab+python(CPU only)配置

    首先声明本教程可以适用于vs2015 和vs2013 .以vs2015为例. 安装必备软件 vs 2015 /vs2013 matlab 2016a(64bit) 推荐使用Anaconda 2.7 或 ...

  6. 源代码可以从应用提取码_大规模下加速源代码分析

    引用:Upadhyaya G , Rajan H . On Accelerating Source Code Analysis At Massive Scale[J]. IEEE Transactio ...

  7. Abaqus CPU并行计算 加速计算信息汇总

    Abaqus CPU并行计算 加速计算信息汇总 下面是网络上https://www.eng-tips.com/viewthread.cfm?qid=445089的答疑: In Abaqus CAE, ...

  8. tf-faster-rcnn在cpu下运行demo、测试和训练自己的数据集

    1.环境配置 官方给出的Faster R-CNN的代码是caffe框架下的,我对caffe不是很了解,一直用的是tensorflow环境,所以去网上找了一下用tensorflow实现的Faster R ...

  9. Linux中Python程序CPU占用高排查

    Linux中Python程序CPU占用高排查,Linux中Python程序CPU占用高排查,Linux中Python程序CPU占用高排查 kafka-python==2.0.2和 gevent 新版本 ...

最新文章

  1. 深度:Leap Motion手势识别大揭秘
  2. 谁把20岁上下的你给洗脑了
  3. 等保数据备份和恢复关键点,这些你该知道!
  4. 数据库设计原则与开发规范,你知道多少?
  5. kali 安装vmware 14 for linux 出现问题
  6. JS 字符串去除首尾空格
  7. 为什么一打电话就显示服务器故障,手机打电话黑屏怎么回事?手机打电话时出现黑屏情况的解决办法介绍...
  8. Privacy Policy of Clone App
  9. typescript工程_使用TypeScript构建游戏。 工程图网格2/5
  10. 普通人卖什么才能赚到人生的第一桶金?
  11. SkeyeVSS实现RTSP、Onvif监控摄像头网页无插件化直播监控解决方案
  12. 如何给未来的自己写一封信(邮件) -- 方法
  13. ln的c语言表达式,c程序中语句中如何表示ln函数?
  14. 关于vue中axios拦截器的使用
  15. 【javascript】设计模式
  16. 怎么做个修改ip服务器,自己做一个服务器怎么固定ip地址
  17. springBoot下的ftp下载
  18. GPB | KaKs_Calculator 3.0:计算编码与非编码序列的选择压力
  19. 2 Z变换、fifter、freqz等离散系统相关函数MATLAB实现
  20. 【P4343】【二分】[SHOI2015]自动刷题机

热门文章

  1. user agent stylesheet对格式的影响
  2. Android开发工具——ADB(Android Debug Bridge) 一概览
  3. Spring 容器AOP的实现原理——动态代理
  4. Android开发--Matrix(一)--实现图片的动态放大缩小
  5. golang中base64编码_MySQL中如何将字符串转为base64编码?
  6. linux运行容器,容器与云|如何在 Windows 上运行 Linux 容器
  7. 运行python程序ModuleNotFoundError?pip下载速度太慢?
  8. mysql insert concat_MySQL常用内置函数说明+concat+insert(str,m,n,inser_str)+week(now())+ | 学步园...
  9. python输入一个整数倒序输出_利用Python实现倒序任意整数
  10. 在研究所工作是什么体验?和互联网公司比,你会怎么选?