5分钟快速入门Numba
责任编辑:一颗赛艇     时间:2021-06-06     来源:原创
责任编辑:一颗赛艇
时间:2021-06-06  来源:原创
分类: 开发资源
浏览量: 587

Numba是Python的即时编译器,可以作用在NumPy数组、函数和循环代码上。使用Numba最常见的方式是通过它的装饰器,将装饰器应用到函数上,指示Numba编译它们。当调用numba修饰函数时,代码将会被“即时”编译为机器码执行,使代码可以以机器码速度运行,极大地提高python代码的运行速度。

如何安装?

  • Numba是一个conda包,可以安装Anaconda Python发行版:
$ conda install numba
  • 也可以通过Pypi进行安装
$ pip install numba

当然,可以通过源码进行编译安装,但不推荐第一次适用Numba的用户使用。

Numba常常被作为核心库使用,所以其依赖库很少,当然,一些额外的功能需要一些可选的依赖库的支持:

  • scipy - 以支持编译 numpy.linalg 函数。
  • colorama - 以支持回溯或错误消息中的颜色高亮。
  • pyyaml - 以支持通过Yaml文件配置Numba.
  • icc_rt - 以支持使用英特尔 SVML (高性能短向量数学库, 仅支持x86_64架构). 安装指南参见 performance tips.

Numba如何编译代码?

这取决于你的代码是什么形式的,如果代码主要为数学运算,使用了较多的NumPy计算或者有很多循环操作,那么Numba将会是一个很好的选择。在下面的例子中,将采用Numba最基本的JIT装饰器@jit,加速编写好的一些函数。

Numba可以很好地处理如下代码:

from numba import jit
import numpy as np

x = np.arange(100).reshape(10, 10)

@jit(nopython=True) # Set "nopython" mode for best performance, equivalent to @njit
def go_fast(a): # Function is compiled to machine code when called the first time
    trace = 0.0
    for i in range(a.shape[0]):   # Numba likes loops
        trace += np.tanh(a[i, i]) # Numba likes NumPy functions
    return a + trace              # Numba likes NumPy broadcasting

print(go_fast(x))

但如下的代码,Numba的加速效果将不佳:

from numba import jit
import pandas as pd

x = {'a': [1, 2, 3], 'b': [20, 30, 40]}

@jit
def use_pandas(a): # Function will not benefit from Numba jit
    df = pd.DataFrame.from_dict(a) # Numba doesn't know about pd.DataFrame
    df += 1                        # Numba doesn't understand what this is
    return df.cov()                # or this!

print(use_pandas(x))

注意,Numba不支持Pandas库,因此Numba会简单地通过解释器运行这段代码,而且还会增加Numba内部开销的成本!

什么是 nopython 模式?

Numba @jit装饰器一般以两种编译模式运行,nopython模式和object模式。在上面的go_fast例子中,@jit装饰器中设置了nopython=True;这是指示Numba在nopython模式下操作。nopython编译模式的行为本质上是编译修饰函数,使其完全运行而不需要Python解释器的参与。这是使用Numba jit装饰器的最佳实践方式,因为它能带来最好的性能。
如果在nopython模式下编译失败,Numba可以使用对象模式编译。如果没有设置nopython=True(如上面的use_pandas例子所示),@jit装饰器将采用回退模式,在这种模式下,Numba将识别它可以编译的循环,并将这些循环编译成在机器码中运行的函数,然后在解释器中运行其余的代码。为了获得最佳性能,应避免使用这种模式!

如何衡量Numba的表现?

如何衡量Numba的性能?

首先,Numba必须根据给定的参数类型编译函数,然后才能执行函数的机器码版本,编译的过程需要一定的时间。但是,一旦编译完成,Numba会缓存编译好的机器码版本,用于提供特定类型的参数。如果再次使用相同的类型调用它,它可以重用缓存的版本,而不必再次编译。

在度量性能时,在第一次运行过程中,应考虑上述行为,而不只用一个简单的计时器来计时代码,其中包括在执行时间中编译函数所花费的时间。

from numba import jit
import numpy as np
import time

x = np.arange(100).reshape(10, 10)

@jit(nopython=True)
def go_fast(a): # Function is compiled and runs in machine code
    trace = 0.0
    for i in range(a.shape[0]):
        trace += np.tanh(a[i, i])
    return a + trace

# DO NOT REPORT THIS... COMPILATION TIME IS INCLUDED IN THE EXECUTION TIME!
start = time.time()
go_fast(x)
end = time.time()
print("Elapsed (with compilation) = %s" % (end - start))

# NOW THE FUNCTION IS COMPILED, RE-TIME IT EXECUTING FROM CACHE
start = time.time()
go_fast(x)
end = time.time()
print("Elapsed (after compilation) = %s" % (end - start))

运行时间

Elapsed (with compilation) = 0.33030009269714355
Elapsed (after compilation) = 6.67572021484375e-06

衡量Numba JIT对代码影响的一个好方法是使用timeit模块函数来计时执行,因此,可以在第一次执行中适应编译时间。如果编译时间是个问题,Numba JIT支持已编译函数的磁盘缓存,并且还支持提前编译模式。

Numba有多快呢?

Numba读取修饰函数的Python字节码,并将其与关于函数输入参数类型的信息结合起来。分析和优化代码,最后使用LLVM编译器库生成机器码版本,并兼容当前的CPU,且以后每次调用函数时都会使用编译后的版本。

其他的主要亮点

Numba有相当多的装饰器,前面主要介绍了@jit,但也有:

  • @njit -  @jit(nopython=True) 的简写,方便快速使用
  • @vectorize - 用于生成Numpy的 ufunc 函数 (支持所有的 ufunc 方法). Docs are here.
  • @guvectorize - 用于生成通用的NumPyufunc 函数. Docs are here.
  • @stencil - 将函数声明为类似于模板的操作的内核. Docs are here.
  • @jitclass - 可用于编译Python类. Docs are here.
  • @cfunc - 声明一个函数用于本机回调(从C/ c++等调用). Docs are here.
  • @overload - 注册一个函数实现以供在nopython模式下使用, 如 @overload(scipy.special.j0). Docs are here.

一些装饰器提供的额外选项:

  • parallel = True - 为函数提供自动并行运行。
  • fastmath = True - 为函数提供快速的数学运算。

ctypes / cffi / cython互操作性:

  • cffi - 支持在nopython模式下调用CFFI函数。
  • ctypes - 在nopython模式下支持调用ctypes包装函数。
  • Cython导出的函数都是可调用的。

GPU加速

Numba支持Nvidia CUDA和(实验性的)AMD ROC图形处理器。你可以用纯Python编写一个内核,让Numba处理计算数据。详细可参见CUDAROC

 

参考:https://numba.readthedocs.io/en/stable/user/5minguide.html


来源:原创

点赞人: 庄SIR  王王木木  公子老狄 

吃炸鸡  回复 2021-10-19 22:39:10
赞!
庄SIR  回复 2021-08-31 09:49:59
学到了
齐琪  回复 2021-07-21 21:14:40
学到了
绿豆鲨  回复 2021-07-15 08:00:49
学到了
庄SIR  回复 2021-07-14 13:02:51
学到啦
sky  回复 2021-06-26 17:52:16
学到了
宇宙最帅靓仔  回复 2021-06-24 15:35:47
学到啦
回复:

Copyright © 2021 .长沙麦涛网络科技有限公司 All rights reserved. 湘ICP备20015126号-2
联系我们