【实用小功能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开发一个图像标注与OCR识别工具

《使用Python开发一个图像标注与OCR识别工具》:本文主要介绍一个使用Python开发的工具,允许用户在图像上进行矩形标注,使用OCR对标注区域进行文本识别,并将结果保存为Excel文件,感兴... 目录项目简介1. 图像加载与显示2. 矩形标注3. OCR识别4. 标注的保存与加载5. 裁剪与重置图像

使用Python实现表格字段智能去重

《使用Python实现表格字段智能去重》在数据分析和处理过程中,数据清洗是一个至关重要的步骤,其中字段去重是一个常见且关键的任务,下面我们看看如何使用Python进行表格字段智能去重吧... 目录一、引言二、数据重复问题的常见场景与影响三、python在数据清洗中的优势四、基于Python的表格字段智能去重

Spring AI集成DeepSeek三步搞定Java智能应用的详细过程

《SpringAI集成DeepSeek三步搞定Java智能应用的详细过程》本文介绍了如何使用SpringAI集成DeepSeek,一个国内顶尖的多模态大模型,SpringAI提供了一套统一的接口,简... 目录DeepSeek 介绍Spring AI 是什么?Spring AI 的主要功能包括1、环境准备2

Python中如何控制小数点精度与对齐方式

《Python中如何控制小数点精度与对齐方式》在Python编程中,数据输出格式化是一个常见的需求,尤其是在涉及到小数点精度和对齐方式时,下面小编就来为大家介绍一下如何在Python中实现这些功能吧... 目录一、控制小数点精度1. 使用 round() 函数2. 使用字符串格式化二、控制对齐方式1. 使用

Python如何快速下载依赖

《Python如何快速下载依赖》本文介绍了四种在Python中快速下载依赖的方法,包括使用国内镜像源、开启pip并发下载功能、使用pipreqs批量下载项目依赖以及使用conda管理依赖,通过这些方法... 目录python快速下载依赖1. 使用国内镜像源临时使用镜像源永久配置镜像源2. 使用 pip 的并

jdk21下载、安装详细教程(Windows、Linux、macOS)

《jdk21下载、安装详细教程(Windows、Linux、macOS)》本文介绍了OpenJDK21的下载地址和安装步骤,包括Windows、Linux和macOS平台,下载后解压并设置环境变量,最... 目录1、官网2、下载openjdk3、安装4、验证1、官网官网地址:OpenJDK下载地址:Ar

SpringBoot集成图片验证码框架easy-captcha的详细过程

《SpringBoot集成图片验证码框架easy-captcha的详细过程》本文介绍了如何将Easy-Captcha框架集成到SpringBoot项目中,实现图片验证码功能,Easy-Captcha是... 目录SpringBoot集成图片验证码框架easy-captcha一、引言二、依赖三、代码1. Ea

Python如何实现读取csv文件时忽略文件的编码格式

《Python如何实现读取csv文件时忽略文件的编码格式》我们再日常读取csv文件的时候经常会发现csv文件的格式有多种,所以这篇文章为大家介绍了Python如何实现读取csv文件时忽略文件的编码格式... 目录1、背景介绍2、库的安装3、核心代码4、完整代码1、背景介绍我们再日常读取csv文件的时候经常

基于Python实现多语言朗读与单词选择测验

《基于Python实现多语言朗读与单词选择测验》在数字化教育日益普及的今天,开发一款能够支持多语言朗读和单词选择测验的程序,对于语言学习者来说无疑是一个巨大的福音,下面我们就来用Python实现一个这... 目录一、项目概述二、环境准备三、实现朗读功能四、实现单词选择测验五、创建图形用户界面六、运行程序七、

解读docker运行时-itd参数是什么意思

《解读docker运行时-itd参数是什么意思》在Docker中,-itd参数组合用于在后台运行一个交互式容器,同时保持标准输入和分配伪终端,这种方式适合需要在后台运行容器并保持交互能力的场景... 目录docker运行时-itd参数是什么意思1. -i(或 --interactive)2. -t(或 --