【实用小功能10】python运行加速神器——numba(详细教学版)

2023-10-18 04:28

本文主要是介绍【实用小功能10】python运行加速神器——numba(详细教学版),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

目录

      • 1. 为什么python这么慢?
        • 1.1 动态变量
        • 1.2. 解释性语言
      • 2. Numba的介绍和使用
        • 2.1 numba加速python小实例
        • 2.2 个人经验
        • 2.3 其他

1. 为什么python这么慢?

python比c++慢,尤其是存在循环的情况下,python和c+的区别主要有:

1.1 动态变量

c++中需要对变量类型有严格的定义,比如int或者float类型。但是python不需要,它去掉了变量申明和数据类型。python是一种动态类型语言,它会在做运算的时候根据变量的值自动推断出其类型,这种动态类型的特性使得python编写更加简单和灵活,但同时增加了一定的时间开销,反观c/c++在运算时则只是简单的内存读写和机器指令(加减乘除…),所以c/c++的速度比python快很多。

1.2. 解释性语言

c/c++是编译型语言,需要先将源代码编译成机器码,然后再运行程序。

python是解释性语言,它的源代码是直接由解释器解释执行的,这意味着在编写python代码时,不需要先将代码编译成可执行文件,而是可以直接运行代码。所以python的执行速度相较于c/c++会慢很多。

这个问题的一种解决方法就是即时编译JIT(Just-in-time compilation)JIT编译器会动态地将高级语言编写的代码转换为机器码,可以直接由计算机的处理器执行,这是在运行时完成的,也就是代码执行之前,因此称为“即时”。JIT针对特定的硬件和操作系统进行代码优化,可以使得python代码获得显著的性能提升。

2. Numba的介绍和使用

github主页:https://github.com/numba/numba

在线文档:https://numba.readthedocs.io/en/stable/index.html

可直接pip/conda下载库

conda install numba
pip install numba

numba非常适合于使用了numpy数组、函数和循环的代码,使用的方法就是装饰器,用它!用的好时间节省个几十倍。numba的可使用范围:

  • 操作系统:Windows (64 bit), OSX, Linux (64 bit).
  • 架构:x86, x86_64, ppc64le, armv8l (aarch64), M1/Arm64.
  • GPU:Nvidia CUDA.
  • CPython
  • NumPy版本:1.22~1.25
2.1 numba加速python小实例
  • 使用python计算一个矩阵的所有元素的和

  • 原始代码

def cal_sum(a): result = 0 for i in range(a.shape[0]): for j in range(a.shape[1]): result += a[i, j] return result start = time.perf_counter()
a = np.random.random((5000, 5000)) 
result = cal_sum(a)
end = time.perf_counter()
print("原始代码耗时:{}s".format((end - start)))#OUT:
#原始代码耗时:5.725140199996531s
  • 使用numba加速
import numba@numba.jit(nopython=True) 
def cal_sum(a): result = 0 for i in range(a.shape[0]): for j in range(a.shape[1]): result += a[i, j] return result start = time.perf_counter()
a = np.random.random((5000, 5000)) 
result = cal_sum(a)
end = time.perf_counter()
print("加速后耗时:{}s".format((end - start)))#OUT:
#加速后耗时:0.2892118000017945s

@jit(nopython=True)@njit是等同的,这个选项指示numba在编译时尽可能地避免使用python对象,将python代码转换为更快的机器码,而不是使用python解释器来执行代码。

  • 多次调用同一个使用了numba加速的函数

numba在第首次调用函数的时候进行了编译,但当编译发生后,numba会将该函数的机器码进行缓存,如果再次调用该函数,它会直接从缓存中加载,而不需要再次编译。简而言之,在一段代码中的使用了numba的函数,第二次、第三次…调用该函数运算都要比第一次耗时更少

x = np.arange(100).reshape(10, 10)@jit(nopython=True)
def go_fast(a):trace = 0.0for i in range(a.shape[0]):trace += np.tanh(a[i, i])return a + tracestart = time.perf_counter()
go_fast(x)
end = time.perf_counter()
print("首次调用耗时:{}s".format((end - start)))start = time.perf_counter()
go_fast(x)
end = time.perf_counter()
print("再次调用耗时:{}s".format((end - start)))#OUT:
#首次调用耗时:0.16958359999989625s
#再次调用耗时:4.7599998652003706e-05s
  • 使用并行加速【失败,原因还未知】

官方使用说明网址:numba-parallel

拿了官方的代码对比了下未使用并行和使用并行的,但是并行的反而更慢,没仔细细究缘由。

from numba import njit@njit()
def prange_test(A):s = 0for i in range(A.shape[0]):s += A[i]return sstart = time.perf_counter()
a = np.arange(1000)
result = prange_test(a)
end = time.perf_counter()
print("无并行耗时:{}s".format((end - start)))#OUT:
#无并行耗时:0.07213479999336414s
from numba import njit, prange@njit(parallel=True)
def prange_test(A):s = 0# Without "parallel=True" in the jit-decorator# the prange statement is equivalent to rangefor i in prange(A.shape[0]):s += A[i]return sstart = time.perf_counter()
a = np.arange(1000)
result = prange_test(a)
end = time.perf_counter()
print("并行耗时:{}s".format((end - start)))#OUT:
#并行耗时:0.36391139999614097s
2.2 个人经验

上面的函数比较简单,但是在实际使用中我们的函数可能复杂很多,简单地直接在函数上添加一个装饰器会出现各种报错,我们需要针对问题调整函数代码,大概陈列几个我遇到的问题及解决的方法。

  • 报错1
TypingError: Failed in nopython mode pipeline (step: nopython frontend)
Cannot infer the type of variable 'result', have imprecise type: list(undefined)<iv=None>. For Numba to be able to compile a list, the list must have a known and
precise type that can be inferred from the other variables. Whilst sometimes
the type of empty lists can be inferred, this is not always the case, see this
documentation for help:https://numba.pydata.org/numba-doc/latest/user/troubleshoot.html#my-code-has-an-untyped-list-problem

有些报错,会给个网址告诉你报错原因,点进去认真看下然后照着意思修改修改自己的代码就行了,但这个问题的解决方法如下:

@numba.jit(nopython=True) 
def test(): result, result1 = [], 0return result, result1test()# 改为
@numba.jit(nopython=True) 
def test(): result = []result1 = 0return result, result1test()
  • 报错2:
TypingError: Failed in nopython mode pipeline (step: nopython frontend)
Unknown attribute 'tolist' of type array(float32, 1d, C)...
Untyped global name 'input': Cannot determine Numba type of <class 'method'>

这样的问题是因为numba现在还有一些函数是不支持,比如上面python自带的input()函数和数组的tolist()函数,遇到这些问题的时候解决方法就是使用同样功能的且numba支持的函数or自己重写一个函数。

  • 报错3
def test_func():return True@jit(nopython=True)
def test(): flag = test_func()test()
TypingError: Failed in nopython mode pipeline (step: nopython frontend)
Untyped global name 'test_func': Cannot determine Numba type of <class 'function'>

这个问题是numba不支持函数中嵌套自己的函数,解决方法就是把调用的函数合并到一个函数中。

  • 报错4

会有一些与list列表相关的报错,numba貌似很不支持列表操作,尤其是嵌套列表类似[[[1,2],[2,3]],[[2,2],[8,3]]],解决方法是将这种列表改为数组进行操作。

2.3 其他

numba还提供了很多其他加速方法(我还没试):

  • 想节省编译时间,numba提供了提前编译模式:Ahead-of-Time compilation
  • 使用GPU:cuda-index

参考:Python 提速大杀器之 numba 篇

这篇关于【实用小功能10】python运行加速神器——numba(详细教学版)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/230158

相关文章

python: 多模块(.py)中全局变量的导入

文章目录 global关键字可变类型和不可变类型数据的内存地址单模块(单个py文件)的全局变量示例总结 多模块(多个py文件)的全局变量from x import x导入全局变量示例 import x导入全局变量示例 总结 global关键字 global 的作用范围是模块(.py)级别: 当你在一个模块(文件)中使用 global 声明变量时,这个变量只在该模块的全局命名空

如何用Docker运行Django项目

本章教程,介绍如何用Docker创建一个Django,并运行能够访问。 一、拉取镜像 这里我们使用python3.11版本的docker镜像 docker pull python:3.11 二、运行容器 这里我们将容器内部的8080端口,映射到宿主机的80端口上。 docker run -itd --name python311 -p

C++11第三弹:lambda表达式 | 新的类功能 | 模板的可变参数

🌈个人主页: 南桥几晴秋 🌈C++专栏: 南桥谈C++ 🌈C语言专栏: C语言学习系列 🌈Linux学习专栏: 南桥谈Linux 🌈数据结构学习专栏: 数据结构杂谈 🌈数据库学习专栏: 南桥谈MySQL 🌈Qt学习专栏: 南桥谈Qt 🌈菜鸡代码练习: 练习随想记录 🌈git学习: 南桥谈Git 🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈�

让树莓派智能语音助手实现定时提醒功能

最初的时候是想直接在rasa 的chatbot上实现,因为rasa本身是带有remindschedule模块的。不过经过一番折腾后,忽然发现,chatbot上实现的定时,语音助手不一定会有响应。因为,我目前语音助手的代码设置了长时间无应答会结束对话,这样一来,chatbot定时提醒的触发就不会被语音助手获悉。那怎么让语音助手也具有定时提醒功能呢? 我最后选择的方法是用threading.Time

【Python编程】Linux创建虚拟环境并配置与notebook相连接

1.创建 使用 venv 创建虚拟环境。例如,在当前目录下创建一个名为 myenv 的虚拟环境: python3 -m venv myenv 2.激活 激活虚拟环境使其成为当前终端会话的活动环境。运行: source myenv/bin/activate 3.与notebook连接 在虚拟环境中,使用 pip 安装 Jupyter 和 ipykernel: pip instal

【机器学习】高斯过程的基本概念和应用领域以及在python中的实例

引言 高斯过程(Gaussian Process,简称GP)是一种概率模型,用于描述一组随机变量的联合概率分布,其中任何一个有限维度的子集都具有高斯分布 文章目录 引言一、高斯过程1.1 基本定义1.1.1 随机过程1.1.2 高斯分布 1.2 高斯过程的特性1.2.1 联合高斯性1.2.2 均值函数1.2.3 协方差函数(或核函数) 1.3 核函数1.4 高斯过程回归(Gauss

【学习笔记】 陈强-机器学习-Python-Ch15 人工神经网络(1)sklearn

系列文章目录 监督学习:参数方法 【学习笔记】 陈强-机器学习-Python-Ch4 线性回归 【学习笔记】 陈强-机器学习-Python-Ch5 逻辑回归 【课后题练习】 陈强-机器学习-Python-Ch5 逻辑回归(SAheart.csv) 【学习笔记】 陈强-机器学习-Python-Ch6 多项逻辑回归 【学习笔记 及 课后题练习】 陈强-机器学习-Python-Ch7 判别分析 【学

nudepy,一个有趣的 Python 库!

更多资料获取 📚 个人网站:ipengtao.com 大家好,今天为大家分享一个有趣的 Python 库 - nudepy。 Github地址:https://github.com/hhatto/nude.py 在图像处理和计算机视觉应用中,检测图像中的不适当内容(例如裸露图像)是一个重要的任务。nudepy 是一个基于 Python 的库,专门用于检测图像中的不适当内容。该

Spring框架5 - 容器的扩展功能 (ApplicationContext)

private static ApplicationContext applicationContext;static {applicationContext = new ClassPathXmlApplicationContext("bean.xml");} BeanFactory的功能扩展类ApplicationContext进行深度的分析。ApplicationConext与 BeanF

pip-tools:打造可重复、可控的 Python 开发环境,解决依赖关系,让代码更稳定

在 Python 开发中,管理依赖关系是一项繁琐且容易出错的任务。手动更新依赖版本、处理冲突、确保一致性等等,都可能让开发者感到头疼。而 pip-tools 为开发者提供了一套稳定可靠的解决方案。 什么是 pip-tools? pip-tools 是一组命令行工具,旨在简化 Python 依赖关系的管理,确保项目环境的稳定性和可重复性。它主要包含两个核心工具:pip-compile 和 pip