Numba编译器的介绍与应用,1.介绍

Numba 是 python 的即时(Just-in-time)编译器,即当你调用 python 函数时,你的全部或部分代码就会被转换为“即时”执行的机器码,它将以你的本地机器码速度运行!它由 Anaconda 公司赞助,并得到了许多其他组织的支持。

在 Numba 的帮助下,你可以加速所有计算负载比较大的 python 函数(例如循环)。它还支持 numpy 库!所以,你也可以在你的计算中使用 numpy,并加快整体计算,因为 python 中的循环非常慢。你还可以使用 python 标准库中的 math 库的许多函数,如 sqrt 等。有关所有兼容函数的完整列表,请查看 此处。

2.为什么选择 Numba?

那么,当有像 cython 和 Pypy 之类的许多其他编译器时,为什么要选择 numba?

原因很简单,这样你就不必离开写 python 代码的舒适区。是的,就是这样,你根本不需要为了获得一些的加速来改变你的代码,这与你从类似的具有类型定义的 cython 代码获得的加速相当。那不是很好吗?

你只需要添加一个熟悉的 python 功能,即添加一个包装器(一个装饰器)到你的函数上。类的装饰器也在开发中了。

所以,你只需要添加一个装饰器就可以了。例如:

cd ~/pythia/data
from numba import jit
@jit
def function(x):# your loop or numerically intensive computationsreturn x

这仍然看起来像一个原生 python 代码,不是吗?

3.如何使用 Numba?

Numba 使用 LLVM 编译器基础结构 将原生 python 代码转换成优化的机器码。使用 numba 运行代码的速度可与 C/C++ 或 Fortran 中的类似代码相媲美。

以下是代码的编译方式:

首先,Python 函数被传入,优化并转换为 numba 的中间表达,然后在类型推断(type inference)之后,就像 numpy 的类型推断(所以 python float 是一个 float64),它被转换为 LLVM 可解释代码。然后将此代码提供给 LLVM 的即时编译器以生成机器码。

你可以根据需要在运行时或导入时 生成 机器码,导入需要在 CPU(默认)或 GPU 上进行。

4.使用 numba 的基本功能

(只需要加上 @jit !)

为了获得最佳性能,numba 实际上建议在你的 jit 装饰器中加上 nopython=True 参数,加上后就不会使用 Python 解释器了。或者你也可以使用 @njit。如果你加上 nopython=True的装饰器失败并报错,你可以用简单的 @jit 装饰器来编译你的部分代码,对于它能够编译的代码,将它们转换为函数,并编译成机器码。然后将其余部分代码提供给 python 解释器。

所以,你只需要这样做:

from numba import njit, jit
@njit      # or @jit(nopython=True)
def function(a, b):# your loop or numerically intensive computationsreturn result

当使用 @jit 时,请确保你的代码有 numba 可以编译的内容,比如包含库(numpy)和它支持的函数的计算密集型循环。否则它将不会编译任何东西,并且你的代码将比没有使用 numba 时更慢,因为存在 numba 内部代码检查的额外开销。

还有更好的一点是,numba 会对首次作为机器码使用后的函数进行缓存。因此,在第一次使用之后它将更快,因为它不需要再次编译这些代码,如果你使用的是和之前相同的参数类型。

如果你的代码是 可并行化 的,你也可以传递 parallel=True 作为参数,但它必须与 nopython=True 一起使用,目前这只适用于CPU。

你还可以指定希望函数具有的函数签名,但是这样就不会对你提供的任何其他类型的参数进行编译。例如:

 from numba import jit, int32@jit(int32(int32, int32))def function(a, b):# your loop or numerically intensive computationsreturn result# or if you haven t imported type names# you can pass them as string@jit( int32(int32, int32) )def function(a, b):# your loop or numerically intensive computationsreturn result

现在你的函数只能接收两个 int32 类型的参数并返回一个 int32 类型的值。通过这种方式,你可以更好地控制你的函数。如果需要,你甚至可以传递多个函数签名。

你还可以使用 numba 提供的其他装饰器:

  • @vectorize:允许将标量参数作为 numpy 的 ufuncs 使用,
  • @guvectorize:生成 NumPy 广义上的 ufuncs,
  • @stencil:定义一个函数使其成为 stencil 类型操作的核函数
  • @jitclass:用于 jit 类,
  • @cfunc:声明一个函数用于本地回调(被C/C++等调用),
  • @overload:注册你自己的函数实现,以便在 nopython 模式下使用,例如:@overload(scipy.special.j0)。

Numba 还有 Ahead of time(AOT)编译,它生成不依赖于 Numba 的已编译扩展模块。但:

  • 它只允许常规函数(ufuncs 就不行),
  • 你必须指定函数签名。并且你只能指定一种签名,如果需要指定多个签名,需要使用不同的名字。

它还根据你的CPU架构系列生成通用代码。

5.@vectorize 装饰器

通过使用 @vectorize 装饰器,你可以对仅能对标量操作的函数进行转换,例如,如果你使用的是仅适用于标量的 python 的 math 库,则转换后就可以用于数组。这提供了类似于 numpy 数组运算(ufuncs)的速度。例如:

from numba import jit, int32
@vectorize
def func(a, b):# Some operation on scalarsreturn result

你还可以将 target 参数传递给此装饰器,该装饰器使 target 参数为 parallel 时用于并行化代码,为 cuda 时用于在 cudaGPU 上运行代码。

@vectorize(target="parallel")
def func(a, b):# Some operation on scalarsreturn result

使 target=“parallel” 或 “cuda” 进行矢量化通常比 numpy 实现的代码运行得更快,只要你的代码具有足够的计算密度或者数组足够大。如果不是,那么由于创建线程以及将元素分配到不同线程需要额外的开销,因此可能耗时更长。所以运算量应该足够大,才能获得明显的加速。

IT问答库http://www.mobiletrain.org/qa/

这个视频讲述了一个用 Numba 加速用于计算流体动力学的Navier Stokes方程的例子:

6.在GPU上运行函数

你也可以像装饰器一样传递 @jit 来运行 cuda/GPU 上的函数。为此你必须从 numba 库中导入 cuda。但是要在 GPU 上运行代码并不像之前那么容易。为了在 GPU 上的数百甚至数千个线程上运行函数,需要先做一些初始计算。实际上,你必须声明并管理网格,块和线程的层次结构。这并不那么难。

要在GPU上执行函数,你必须定义一个叫做 核函数 或 设备函数 的函数。首先让我们来看 核函数。

关于核函数要记住一些要点:

  • 核函数在被调用时要显式声明其线程层次结构,即块的数量和每块的线程数量。你可以编译一次核函数,然后用不同的块和网格大小多次调用它。
  • 核函数没有返回值。因此,要么必须对原始数组进行更改,要么传递另一个数组来存储结果。为了计算标量,你必须传递单元素数组。
# Defining a kernel function
from numba import cuda
@cuda.jit
def func(a, result):# Some cuda related computation, then# your computationally intensive code.# (Your answer is stored in  result )

因此,要启动核函数,你必须传入两个参数:

  • 每块的线程数,
  • 块的数量。

例如:

threadsperblock = 32
blockspergrid = (array.size + (threadsperblock - 1)) // threadsperblock
func[blockspergrid, threadsperblock](array)

每个线程中的核函数必须知道它在哪个线程中,以便了解它负责数组的哪些元素。Numba 只需调用一次即可轻松获得这些元素的位置。

@cuda.jit
def func(a, result):pos = cuda.grid(1)  # For 1D array# x, y = cuda.grid(2) # For 2D arrayif pos < a.shape[0]:result[pos] = a[pos] * (some computation)

为了节省将 numpy 数组复制到指定设备,然后又将结果存储到 numpy 数组中所浪费的时间,Numba 提供了一些 函数 来声明并将数组送到指定设备,如:numba.cuda.device_array,numba.cuda。device_array_like,numba.cuda.to_device 等函数来节省不必要的复制到 cpu 的时间(除非必要)。

另一方面,设备函数 只能从设备内部(通过核函数或其他设备函数)调用。比较好的一点是,你可以从 设备函数 中返

from numba import cuda
@cuda.jit(device=True)
def device_function(a, b):return a + b

你还应该在这里查看 Numba 的 cuda 库支持的功能。

Numba 在其 cuda 库中也有自己的原子操作,随机数生成器,共享内存实现(以加快数据的访问)等功能。

ctypes/cffi/cython 的互用性:

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

Numba编译器的介绍与应用相关推荐

  1. 精读《手写 SQL 编译器 - 文法介绍》

    1 引言 文法用来描述语言的语法规则,所以不仅可以用在编程语言上,也可用在汉语.英语上. 2 精读 我们将一块语法规则称为 产生式,使用 "Left → Right" 表示任意产生 ...

  2. 计算机系统要素--第六章,01-HACK汇编编译器模块介绍

    从零开始构建现代计算机--第六章,01-HACK汇编编译器模块介绍 语法分析器(Parser) 编码(Code) 无符号程序的汇编编译器 符号表(Symbol Table) 有符号程序的汇编编译器 H ...

  3. Tiny语言编译器简单介绍

    1.简单介绍:编译器是将一种语言翻译成还有一种语言的程序.编译器将源程序的代码作为输出,从而产生用目标语言编写的等价程序.比如源码为C/C++等高级语言,那么目标语言就是目标机器的机器代码.也就是能够 ...

  4. [转] 编译器Clang介绍

    LLVM 与 Clang 介绍 { 撰文/guest } 来源:http://linuxtoy.org/archives/llvm-and-clang.html LLVM 是 Low Level Vi ...

  5. 业界编译器Clang介绍

    http://baike.baidu.com/link?url=2cAQ-ZePNxPoPNll06fdZKaG5oSOpAhfmCoJ5hIS1sBG1Psy9c8wlcguVAsronSVYDc5 ...

  6. Keil C系列之编译器介绍(1)

    1 Cx51编译器的介绍 C编程语言是一种通用编程语言,它提供了代码效率.结构化编程元素和丰富的操作符集.C语言不是一门很大的语言,也不是为任何特定的应用领域而设计的.C语言的通用性和它的无限制相结合 ...

  7. MPI编译环境及编译器介绍

    一.基本编译器介绍 集群配置有三套基本的编译器:1.GCC编译器,2.PGI编译器,3.INTEL编译器.介绍如下: GCC C编译器 gcc C++编译器 g++ Fortran 77编译器 g77 ...

  8. 在keil上编译linux下的STM32裸机工程 arm 编译器介绍

    Keil5.15使用GCC编译器编译STM32工程 https://blog.csdn.net/lan120576664/article/details/46806991 linux中keil如何编译 ...

  9. c编译器哪个好?6款c编译器介绍

    许多朋友经常混淆c编译器和c编辑器,注意,c编译器的作用在于编译,而c编辑器在于编写代码.对于c编译器,小编曾带来诸多文章.但有网友提问,有没有较为推荐的c编译器.为解决大家的疑问,本文将对6款c编译 ...

最新文章

  1. 卷积神经网络模型可解释性
  2. 空间服务器有问题是系统问题吗,服务器空间租用两个主要问题要留意
  3. POI SXSSFWorkbook 实现大批量数据 导出
  4. java数据结构之选择排序
  5. 多角度了解科大讯飞公司之一(语音识别)
  6. ospf 几种LSA类型的总结
  7. 蓝屏代码0x00000109 错误分析
  8. 32位服务器系统支持8G内存,32位系统怎么支持8g内存条win10 64位系统闲置服务器...
  9. Bootstrap-table固定表头并美化表头
  10. 知识图谱构建技术简介
  11. win7系统提示“此windows副本不是正版” 解决方案
  12. 【 vue 】局部样式与全局样式
  13. mysql查最高薪水,使用子查询查找MySQL Employee表的最高和第二最高薪水?
  14. 7-2 判断是否含敏感词汇
  15. 【c】分数类型的定义 c语言分数类型加减乘除的实现
  16. 我的世界网易怎么下载java材质包_​网易我的世界材质包怎么导入
  17. 《Unity 游戏设计与实现 南梦宫一线程序员的开发实例》学习笔记01
  18. “反百度”,正义?邪恶?
  19. 管理费用明细科目大全!
  20. DNS和IP的WHOIS查询

热门文章

  1. Ajax文本文件静态分页分页
  2. MySQL安全插件:Connection-Control Plugins 的利与弊
  3. Gartner 2020 战略技术趋势- Hyper 自动化
  4. 双11没有那么多战报,其实也挺好
  5. 有限元仿真分析误差来源之材料参数设置,小心为妙!
  6. 培养职场“钻石英语”能力
  7. 认真敲项目(三) select2
  8. 分析技术和方法论营销理论知识框架,营销方面4P、用户使用行为、STP,管理方面5W2H、逻辑树、金字塔、生命周期...
  9. python的ols回归_Python滚动窗口OLS回归估计
  10. 【MAPBOX基础功能】32、实现mapbox的测距功能