为什么c++文件只能执行一次_numba从入门到精通(1)—为什么numba能够加速

真是哭了。。。为什么我之前写的numba教程全没了啊啊啊啊啊啊!!!!?????

只能从头整理了无语。

How Numba and Cython speed up Python code​rushter.com https://blog.csdn.net/helloxiaozhe/article/details/78104975​blog.csdn.net

参考链接见上。

首先回顾一下编译型语言和解释型语言(也经常叫脚本语言):

1、编译型语言,C、C++、Fortran、Pascal、Ada,由编译型语言编写的源程序需要经过编译,汇编和链接才能输出目标代码,然后由机器执行目标代码。目标代码是有机器指令组成,不能独立运行,因为源程序中可能使用了一些汇编程序不能解释引用的库函数,而库函数又不在源程序中,此时还需要链接程序完成外部引用和目标模板调用的链接任务,最后才能输出可执行代码。(例如我们编写c的时候引用了一个自定义的c库函数,则需要进行链接操作)

2、解释型语言,解释器不产生目标机器代码,而是产生中间代码,这种中间代码与机器代码不同,中间代码的解释是由软件支持的,不能直接使用在硬件上。该软件解释器通常会导致执行效率较低,用解释型语言编写的程序是由另一个可以理解中间代码的解释程序执行的。和编译的程序不同的是, 解释程序的任务是逐一将源代码的语句解释成可执行的机器指令,不需要将源程序翻译成目标代码再执行。对于解释型语言,需要一个专门的解释器来执行该程序,每条语句只有在执行是才能被翻译,这种解释型语言每执行一次就翻译一次,因而效率低下

一、python编译过程概述

  当我们执行Python代码的时候,在Python解释器用四个过程“拆解”我们的代码,最终被CPU执行返回给用户。

  首先当用户键入代码交给Python处理的时候会先进行词法分析,例如用户键入关键字或者当输入关键字有误时,都会被词法分析所触发,不正确的代码将不会被执行。

  下一步Python会进行语法分析,例如当"for i in test:"中,test后面的冒号如果被写为其他符号,代码依旧不会被执行。

  下面进入最关键的过程,生成字节码,在执行Python前,Python会生成.pyc文件,这个文件就是字节码,如果我们不小心修改了字节码,Python下次重新编译该程序时会和其上次生成的字节码文件进行比较,如果不匹配则会将被修改过的字节码文件进行覆盖,以确保每次编译后字节码的准确性。

  那么什么是字节码?字节码在Python虚拟机程序里对应的是PyCodeObject对象。.pyc文件是字节码在磁盘上的表现形式。简单来说就是在编译代码的过程中,首先会将代码中的函数、类等对象分类处理,然后生成字节码文件。有了字节码文件,通过python的解释器对字节码进行解释,将每一行的字节码解释成CPU可以直接识别的机器码,执行。

(补充:python解释器的类型有cpython、IPython、PyPy、Jython、IronPython:

Python解释器​www.liaoxuefeng.com
9753a6256197abdef0b96d4a3ab863af.png

所以,综上所属,python的整个从输入到输出的过程如下图:

2bb93040beed0e9b16cb7b0a41b3cba6.png

我们常见的cpython解释器是用c语言的方式来解释字节码的,而numba则是使用LLVM编译技术来解释字节码的。

首先我们来看看numba的简单使用案例与加速情况:

import numpy as np
from numba import jit

a = np.arange(1, 10 ** 7)
b = np.arange(-10 ** 7, -1)


@jit(nopython=True)
def sum_sequence(a, b):
    result = np.zeros_like(a)
    for i in range(len(a)):
        result[i] = a[i] - b[i]
    return result

ee31b64677a11e820d56d9f6bee9906c.png
numba加速的简单案例和结果

然后我们通过dis进行反编译得到python的字节码:

>>> import dis
>>> dis.dis(sum_sequence)
  2           0 LOAD_GLOBAL              0 (np)
              2 LOAD_ATTR                1 (zeros_like)
              4 LOAD_FAST                0 (a)
              6 CALL_FUNCTION            1
              8 STORE_FAST               2 (result)

  3          10 SETUP_LOOP              40 (to 52)
             12 LOAD_GLOBAL              2 (range)
             14 LOAD_GLOBAL              3 (len)
             16 LOAD_FAST                0 (a)
             18 CALL_FUNCTION            1
             20 CALL_FUNCTION            1
             22 GET_ITER
        >>   24 FOR_ITER                24 (to 50)
             26 STORE_FAST               3 (i)

  4          28 LOAD_FAST                0 (a)
             30 LOAD_FAST                3 (i)
             32 BINARY_SUBSCR
             34 LOAD_FAST                1 (b)
             36 LOAD_FAST                3 (i)
             38 BINARY_SUBSCR
             40 BINARY_SUBTRACT
             42 LOAD_FAST                2 (result)
             44 LOAD_FAST                3 (i)
             46 STORE_SUBSCR
             48 JUMP_ABSOLUTE           24
        >>   50 POP_BLOCK

  5     >>   52 LOAD_FAST                2 (result)
             54 RETURN_VALUE

我们之前写的cython本质上还是通过c的编译器来替换掉cpython底层的复杂代码从而实现了加速(比如python的动态类型,涉及到一大堆的类型检查、多态、溢出检查等耗时非常多,但是如果使用cython的静态类型就没有这么多麻烦的问题),

而numba的思路则不太一样,numba是在一个叫做LLVM的编译器上进行编译,Numba将Python字节码转换为LLVM中间表示(IR),请注意,LLVM IR是一种低级编程语言,与汇编语法类似,与Python无关。

Numba模式

Numba有两种模式:nopythonobject。前者不使用Python运行时并生成没有Python依赖的本机代码。本机代码是静态类型的,运行速度非常快。而对象模式使用Python对象和Python C API,而这通常不会显着提高速度。在这两种情况下,Python代码都是使用LLVM编译的。

什么是LLVM?

LLVM是一个编译器,它采用代码的特殊中​​间表示(IR)并将其编译为本机(机器)代码。编译过程涉及许多额外的传递,其中LLVM编译器可以优化IR。LLVM工具链非常擅长优化IR,因此它不仅可以编译Numba的代码,还可以优化它。

整个系统大致如下:

648305b6cda24852fd8f9d9d9794f1b1.png

Numba的优点:

  • 便于使用
  • 自动并行化
  • 支持numpy操作和对象
  • 支持调用GPU

Numba的缺点:

  • debug非常麻烦
  • 无法在nopython模式下与Python及其模块进行交互,numba目前在nopython模式下支持python模块有限,比如pandas是不支持的,但是不支持意味着无法加速并不意味着不能运行。
  • 对python中的类class支持有限
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值