返回介绍

7.9 Numba

发布于 2024-01-25 21:44:08 字数 1386 浏览 0 评论 0 收藏 0

来自Continuum Analytics的Numba是一个专用于numpy代码的即时编译器,在运行时由LLVM编译器(不是由我们在之前例子中所用的g++或gcc)来编译。它不需要预编译扫描,所以当你用它来运行新代码时,它会根据你的硬件编译每一个注解的函数。漂亮之处就是你提供了一个装饰器告诉它需要集中于哪些函数,接着你就让Numba接手。它的目标是在所有标准numpy代码上运行。

这是一个更年轻的项目(我们使用v0.13),它的API可能会随着每一次发布发生小小的改变,所以认为当前它在研究环境中更有用。如果你使用numpy array,并且有迭代许多次的非向量代码,Numba会给你一个快速而不需付出什么代价的胜利。

使用Numba的一个缺点就是工具链——它使用了LLVM,具有很多的依赖性。我们推荐你使用Continuum的Anaconda发布包,因为它提供了所有一切,否则在一个全新的环境中安装Numba是一个很耗时的任务。

例7-14展示了给我们的核心Julia函数增加@jit装饰器。这就是所需的全部了,numba被导入的事实意味着LLVM机制会在运行时发挥作用,在幕后编译这个函数。

例7-14 让函数应用@jit装修器

from numba import jit
...
@jit()
def calculate_z_serial_purepython(maxiter, zs, cs, output):

如果移除了@jit装饰器,那么这只是用Python2.7运行的Julia演示版的numpy版本,它花费了71秒。增加@jit装饰器后执行时间降低到0.3秒。这已经很接近我们用Cython达成的结果了,然而又没有多出注解的工作量。

如果我们在同一个Python会话中第2次去运行相同的函数,它甚至跑得更快——如果参数类型一样的话就不需要去编译目标函数了,所以整体执行速度就更快。第2次Numba的运行结果等价于我们之前一起使用Cython和numpy获得的结果(所以它几乎不需要做什么就可以达到与Cython一样快的结果!)。PyPy有同样的热身需要。

当用Numba去调试时,值得注意的是你可以让Numba去显示在一个编译函数内部的正在处理的变量类型。在例7-15中,我们可以看到zs被JIT编译器识别为一个复杂的数组。

例7-15 调试推导出的类型

print("zs has type:", numba.typeof(zs))
  array(complex128, 1d, C))

Numba也支持其他形式的自省,比如inspect_types,从而让你可以检查编译代码去看看类型信息在哪里被推导出来。如果类型丢失了,那你就能细化函数的表达方式去帮助Numba得到发现更多的类型推导的机会。

Numba的高级版本,NumbaPro,可以实验性的用OpenMP支持prange并行操作符。实验性的GPU之处也有。这个项目的目标是很轻松地把使用numpy的更慢的Python循环代码转换为运行快速的代码,能在CPU或GPU上运行,这个可以关注一下。

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文