用 Numba 加速 Python 代码,变得像 C++ 一样快 !

Python 提速大杀器之 numba 篇 你是不是曾经有这样的苦恼,python 真的太好用了,但是它真的好慢啊(哭死) ; C++ 很快,但是真的好难写啊,此生能不碰它就不碰它。老天啊,有没有什么两全其美的办法呢?俗话说的好:办法总是比困难多,大家都有这个问题,自然也就有大佬来试着解决这个问题,这就请出我们今天的主角:numba 每次一个Python小技巧! 不过在介绍 numba 之前,我们还是得来看看 python 为什么这么慢: 为什么 python 这么慢 用过 python 的人都知道, 尤其是在有循环的情况下,pytho. 阅读详情

目录

  1. 介绍
  2. 为什么选择 Numba?
  3. Numba 是如何工作的?
  4. 使用 Numba 的基本功能(只需要加上 @jit!)
  5. @vectorize 装饰器
  6. 在 GPU 上运行函数
  7. 扩展阅读
  8. 参考

Python学习交流群:1004391443

注意: 这篇文章的 Jupyter Notebook 代码在我的 Github 上:SpeedUpYourAlgorithms-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 功能,即添加一个包装器(一个装饰器)到您的函数上。类的装饰器也在开发中了。

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

1cd ~/pythia/data
2from numba import jit
3@jit
4def function(x):
5    # your loop or numerically intensive computations
6    return x

 

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

3. 如何使用 Numba?

 

 

 

 

“question mark neon signage” by Emily Morter on Unsplash

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

以下是代码的编译方式:

 

 

 

 

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

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

4. 使用 numba 的基本功能(只需要加上 @jit !)

 

 

 

 

Photo by Charles Etoroma on Unsplash

小菜一碟!

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

所以,您只需要这样做:

1from numba import njit, jit
2@njit      # or @jit(nopython=True)
3def function(a, b):
4    # your loop or numerically intensive computations
5    return result

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

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

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

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

 1from numba import jit, int32
 2@jit(int32(int32, int32))
 3def function(a, b):
 4    # your loop or numerically intensive computations
 5    return result
 6# or if you haven t imported type names
 7# you can pass them as string
 8@jit( int32(int32, int32) )
 9def function(a, b):
10    # your loop or numerically intensive computations
11    return result

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

 

 

 

 

 

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

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

 

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

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

 

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

5. @vectorize 装饰器

 

 

 

 

 

“gray solar panel lot” by American Public Power Association on Unsplash

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

1from numba import jit, int32
2@vectorize
3def func(a, b):
4    # Some operation on scalars
5    return result

 

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

1@vectorize(target="parallel")
2def func(a, b):
3    # Some operation on scalars
4    return result

 

 

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

 

 

 

 

 

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

6. 在GPU上运行函数

 

 

 

 

 

“time-lapsed of street lights” by Marc Sendra martorell on Unsplash

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

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

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

a)核函数在被调用时要显式声明其线程层次结构,即块的数量和每块的线程数量。您可以编译一次核函数,然后用不同的块和网格大小多次调用它。

b)核函数没有返回值。因此,要么必须对原始数组进行更改,要么传递另一个数组来存储结果。为了计算标量,您必须传递单元素数组。

1# Defining a kernel function
2from numba import cuda
3@cuda.jit
4def func(a, result):
5    # Some cuda related computation, then
6    # your computationally intensive code.
7    # (Your answer is stored in  result )

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

  1. 每块的线程数,
  2. 块的数量。

 

例如:

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

 

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

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

 

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

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

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

 

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

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

ctypes/cffi/cython 的互用性:

  • cffi – 在 nopython 模式下支持调用 CFFI 函数。
  • ctypes – 在 nopython 模式下支持调用 ctypes 包装函数。
  • Cython 导出的函数是 可调用 的。
Numba:加速python代码 Numba是一款可以将python函数编译为机器代码的JIT编译器,经过Numba编译的python代码(仅限数组运算),其运行速度可以接近C或FORTRAN语言。普通python语言靠Cython编译的,但是Numba使用Jit编译器可以直接将一个函数转化为机器码。JIT的全称是 Just-in-time,在 numba 里面则特指 Just-in-time compilation(即时编译动态编译(dynamic compilation):指的是“在运行时进行编译”; 阅读详情

相关推荐

Python代码在CPU下加速:Numba入门

Python代码加速 主要考虑代码优化加速,而非代码逻辑优化。 Python代码直接运行GPU是不行的,需要一定的改变,Numba是一个接口,不过本文主要针对CPU下的Python代码加速。 Python解释器工作原理 Python文件执行过程 .py文件通过解释器转化为虚拟机可以执行的字节码(.pyc); 字节码在虚拟机上执行,得到结果; 字节码是一种只能运行在虚拟机上的文件...

漫步量化 5156

python运行加速神器——numba(详细教学版)

如果代码中有循环,耗时恼人,一定要用Numba试试。

weixin_45977690的博客 2万+

Python程序如何用GPU加速:Tesla、CUDA、Numba

概念解析 首先要明白,普通的Python代码是无法使用GPU加速的,只能在GPU上跑针对GPU设计的程序。 硬件加速必须要用硬件语言实现。 查询Python+GPU关键字,除了TensorFlow,另外出镜率比较高的几个概念是:Numba、CUDA、PyCUDA、minpy。 要理解这些,需要对Python的理解更底层一些。 关于计算机的一些底层实现,参见: 《编译型语言与解释型语言如何在计算...

漫步量化 2万+

【深度好文】Python加速库Numba简介

1. Numba是什么? Numba是一款可以将python函数编译为机器代码的JIT编译器,经过Numba编译的python代码(仅限数组运算),其运行速度可以接近C或FORTRAN语言。普通python语言靠CPython编译的,但是Numba使用Jit编译器可以直接将一个函数转化为机器码。 2. 如何安装Numba? 我们可以通过conda或者pip来进行安装,命令如下: $ conda install numba 或者 $ pip install numba 3. 初识Numba 为了加强大家.

sgzqc的专栏 9740

USB接口ESD保护电路:深度剖析与选型建议

USB接口在热插拔和频繁使用中极易遭遇静电放电(ESD)冲击,导致芯片损坏或通信异常。本文结合实际电路设计经验,详解TVS二极管、集成ESD防护器件等方案在USB接口上的应用要点,重点分析钳位电压、结电容、IEC 61000-4-2等级等关键参数对信号完整性与防护效果的影响,助你为USB接口匹配高可靠、低干扰的ESD保护方案。

weixin_36289813的博客 510

SAP物料分类账(ML)避坑指南:激活顺序错了怎么办?从CKMSTART到差异分摊的完整流程

本文详细解析SAP物料分类账(ML)的正确激活顺序与配置流程,帮助用户避免常见陷阱如'LKW无科目'、'在制品重估失败'等问题。从CKMSTART到差异分摊的完整流程,涵盖关键配置节点、典型报错分析与应急处理方案,确保产品成本控制(CO-PC)模块的顺利运行。

weixin_42524708的博客 258

如何正确使用numba给Python加速?

如何正确使用numba给Python加速?

xiqng17111342931的博客 2112

深入浅出CenterFusion

结合论文和代码理解CenterFusion

Untitled的专栏 5104

用 Numba 加速 Python 代码,变得像 C++ 一样快

英文:PuneetGrover,译:zxdefying整理:Python开发者(id:PythonCoder)目录介绍为什么选择 Numba?Numba 是如何工作的...

机器学习算法与Python学习 2941

博通PEX89000 PCIe 5.0交换芯片:如何为AI集群构建高效GPU互联架构

本文深入解析了博通PEX89000 PCIe 5.0交换芯片如何为AI集群构建高效的GPU互联架构。该芯片通过提供高带宽、低延迟的PCIe 5.0交换能力,打破传统GPU通信的带宽瓶颈,并支持多主机共享、资源池化及软件定义拓扑,从而显著提升大规模AI训练与推理任务的效率与资源利用率。

weixin_29214559的博客 411

LAMMPS实战:如何用ReaxFF力场模拟碳氢化合物热解(附完整脚本)

本文提供了一份使用LAMMPS软件中ReaxFF反应力场模拟碳氢化合物热解过程的完整实战指南。内容涵盖从环境准备、力场参数选择、能量最小化,到升温恒温动力学模拟的完整脚本编写,并介绍了基于轨迹文件的产物分析方法,帮助计算化学与材料科学研究者快速上手这一关键的分子动力学仿真技术。

soda5的博客 1099

用Numba加速Python代码,变得像C++ 一样快

如果你加上 nopython=True的装饰器失败并报错,你可以用简单的 @jit 装饰器来编译你的部分代码,对于它能够编译的代码,将它们转换为函数,并编译成机器码。通过使用 @vectorize 装饰器,你可以对仅能对标量操作的函数进行转换,例如,如果你使用的是仅适用于标量的 python 的 math 库,则转换后就可以用于数组。是的,就是这样,你根本不需要为了获得一些的加速来改变你的代码,这与你从类似的具有类型定义的 cython 代码获得的加速相当。通过这种方式,你可以更好地控制你的函数。

Python宋宋的专栏 1351

量子密钥分发系统设计与实现(一):系统基本架构讨论

本文主要对量子密钥分发系统中的基础架构和基于系统的量子密钥协商过程进行了初步讨论,为后期系列文章进行铺垫。

量子领域相关话题 3896

c++获取机器码的代码_用 Numba 加速 Python 代码,变得像 C++ 一样快

1. 介绍Numba 是 python 的即时(Just-in-time)编译器,即当您调用 python 函数时,您的全部或部分代码就会被转换为“即时”执行的机器码,它将以您的本地机器码速度运行!它由 Anaconda 公司赞助,并得到了许多其他组织的支持。在 Numba 的帮助下,您可以加速所有计算负载比较大的 python 函数(例如循环)。它还支持 numpy 库!所以,您也可以在您的计算...

weixin_42318708的博客 365

Copilot在游戏开发中的应用:Unity脚本自动生成实践

2021年GitHub Copilot的发布,为代码自动生成带来了革命性突破。作为基于GPT模型训练的AI辅助编程工具,Copilot能根据注释、函数名、代码上下文,实时生成符合语法和逻辑的代码片段,甚至完整脚本。减少重复劳动:自动生成模板代码(如生命周期、结构),让你专注核心逻辑;降低API学习成本:对Unity特有的组件(RigidbodyAnimator)、类(),Copilot能生成符合最佳实践的调用代码;统一代码风格:通过团队共享提示词模板,让生成的代码符合项目规范;快速原型迭代。

AIGC应用创新大全的博客 1618

AUTOSAR 3万字面试题全面解析(持续更新)

ECU抽象层(EAL)是AUTOSAR架构中的一部分,它位于微控制器抽象层(MCAL)之下,但通常与MCAL一起被提及。EAL的目标是提供一个统一的接口来访问和管理ECU(Electronic Control Unit,电子控制单元)的硬件资源,包括处理器、存储器和外围设备。通过这种抽象,EAL使得上层软件能够以一种标准化的方式与ECU硬件交互,而不需要关心具体的硬件实现细节。EAL解决了硬件异构性带来的问题,即不同ECU可能采用不同类型的处理器和硬件配置。

大模型大数据攻城狮的专栏 5609

python jit_用 Numba 加速 Python 代码,变得像 C++ 一样快

原标题:用 Numba 加速 Python 代码,变得像 C++ 一样快英文:Puneet Grover,译:zxdefying整理:Python开发者(id:PythonCoder)目录介绍为什么选择 Numba?Numba 是如何工作的?使用 Numba 的基本功能(只需要加上 @jit!)@vectorize 装饰器在 GPU 上运行函数参考注意: 这篇文章的 Jupyter Noteboo...

weixin_39633781的博客 363

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

just函数python_用 Numba 加速 Python 代码,变得像 C++ 一样快

(给Python开发者加星标,提升Python技能)英文:PuneetGrover,译:zxdefying,艾凌风校稿整理:Python开发者(id:PythonCoder)目录介绍为什么选择 Numba?Numba 是如何工作的?使用 Numba 的基本功能(只需要加上@jit!)@vectorize 装饰器在 GPU 上运行函数扩展阅读参考注意: 这篇文章的 Jupyter...

weixin_36226933的博客 249

迈瑞BS系列全自动生化分析仪LIS协议接口手册(内含HL7和ASTM)

迈瑞BS系列全自动生化分析仪LIS协议接口手册,内含HL7和ASTM)

怀旧版电脑GBC模拟器

再现原版GBC掌机的界面,电脑运行连游戏界面都一样大小,很怀旧,很真实,(英文版)强烈推荐,很小的文件,很难才找到的。

python 循环加速_用Numba加速Python代码

编译 | sunlei发布 | ATYUN订阅号“我们不能再用Python,它太慢了。”任何长期使用Python的人都可能曾经听过类似的声音。说这句话的人也没有错。与许多其他编程语言相比,Python很慢。Benchmark game有一些比较不同编程语言在不同任务上的速度的可靠的基准。解决这个速度问题的一个常见方法是用C++之类的快速语言重新编写代码,然后在上面抛出一个Python包装...

weixin_39794385的博客 2728

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

上一篇: 用Python快速分析和预测股票价格 !
下一篇: Python进阶记录之requests模块 !
普通网友
博客等级 码龄7年 438粉丝 263原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值