Numba使用汇总

Python 比 C++ 慢很多, 尤其在有循环的情况下。

动态变量:Python 中万物皆是对象,数据是存在对象中。如两个变量的加法,python 每次在做运算的时候都先判断变量的类型,再取出来进行运算,而在 C 中,简单的内存读写和机器指令 ADD 即可。在 C/C++ 中也有可变数据类型,但其声明很复杂,是一种非常令人头疼的结构。

解释性语言:C/C++ 编译性语言最大的好处是其编译过程是发生在运行之前的,源代码在调用前被编译器转换为可执行机器码,节约了大量的时间。

Python 是一种解释性语言,没法做到一次编译,后续可以直接运行,每次运行的时候都要重新将源代码通过解释器转化为机器码。好处就是容易 debug。

解决此问题的重要的技术就是 JIT (Just-in-time compilation):JIT 即时编译技术是在运行时(runtime)将调用的函数或程序段编译成机器码载入内存,以加快程序的执行,就是在第一遍执行一段代码前,先执行编译动作,然后执行编译后的代码。

用 numba 加速 python 代码:numba 以装饰器的形式加在 python 函数上的,用户可以不用管 numba 是如何优化代码的,只需要调用即可。 @jit 装饰器有一个参数 nopython, 用于区分 numba 的运行模式,numba 有两种运行模式:一个是 nopython 模式,另一个就是 object模式。只有在nopython 模式下,才会获得最好的加速效果,如果 numba 发现代码有不能理解的东西,就会自动进入 object 模式,确保程序能够运行的。将装饰器改为 @jit(nopython=True) 或者 @njit,numba 会强制使用加速的方式,不进入 object 模式,如编译不成功,则直接抛出异常。

Python 代码的编译过程有四个阶段:词法分析 -> 语法分析 -> 生成字节码 -> 将字节码解释为机器码执行, 常见的 python 解释器的类型有 cpython、IPython、PyPy、Jython、IronPython,numba 使用 LLVM 编译技术来解释字节码的。

LLVM 是一个编译器,采用字节码,并将其编译为机器码,编译过程涉及许多额外的传递,而 LLVM编译器可以优化字节码,如某些频繁执行的模块,LLVM 可以将其作为 “hot code” 做相应的优化,LLVM 工具链非常擅长优化字节码,不仅可以编译 numba 的代码,还可以优化它。

在第一次调用 numba 装饰的函数时,numba 将在调用期间推断参数类型,numba 会结合给定的参数类型将其编译为机器代码。这个过程是有一定的时间消耗的,但是一旦编译完成,numba 会为所呈现的特定类型的参数缓存函数的机器代码版本,如果再次使用相同的类型调用它,可以重用缓存的机器代码而不必再次编译。在测量性能时,如果只使用一个简单的计时器来计算一次,该计时器包括在执行时编译函数所花费的时间,最准确的运行时间应该是第二次及以后调用函数的运行时间。

调用 numba 显式地指定输入、输出数据的类型,可以加快初次调用的函数时的编译速度

numba 基本对所有的 for 循环代码都有非常好的加速效果,前提是 for 循环里面的代码必须是 numba 能够理解的。一般推荐将代码中密集的计算部分提取出来作为单独的函数实现,并使用 nopython 方式优化,其余部分使用 python 原生代码。

numba 对 numpy 的运算也同样的加速效果。numpy 也没有 numba 转换为机器码快,numba 尤其擅长加速 numpy 的基本运算 (如加法、相乘和平方等等) 。

实际中不是所有的 numpy 函数在使用 numba 后都能获得比较好的加速效果,有时甚至会降低 numpy 的运行速度。在实际使用过程中建议提前测试确认加速效果。通常将 numba 用于加速numpy都是 for 循环和 numpy 一起使用时。 numba 对 numpy 的大部分常用的函数都做了支持。

numba 可以直接用 python 写 CUDA Kernel, 直接在 GPU 上编译和运行 Python 程序,numba 通过将 python 代码直接编译为遵循 CUDA 执行模型的 CUDA 内核和设备函数来支持 CUDA GPU 编程,为了节省将 numpy 数组复制到指定设备,然后又将结果存储到 numpy 数组中所浪费的时间,numba 提供了一些函数来声明并将数组送到指定设备来节省不必要的复制到 cpu 的时间。

常用内存分配函数:

cuda.device_array():在设备上分配一个空向量,类似于numpy.empty();
cuda.to_device():将主机的数据拷贝到设备;
cuda.copy_to_host():将设备的数据拷贝回主机;

numba设置日志打印级别

import logging

numba_logger = logging.getLogger('numba')
numba_logger.setLevel(logging.WARNING)

参考:

Python 提速大杀器之 numba 篇_普通网友的博客-CSDN博客_python numba

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值