numba使用多流

CUDA的多流技术允许并发执行主机计算、设备计算和数据拷贝,提高性能。通过创建非默认流,可以实现计算和数据传输的流水线,减少等待时间。在numba中,可以通过设置核函数和数据拷贝的流参数实现多流操作,从而提升大规模向量运算的效率。

numba使用多流

之前我们讨论的并行,都是线程级别的,即CUDA开启多个线程,并行执行核函数内的代码。GPU最多就上千个核心,同一时间只能并行执行上千个任务。当我们处理千万级别的数据,整个大任务无法被GPU一次执行,所有的计算任务需要放在一个队列中,排队顺序执行。CUDA将放入队列顺序执行的一系列操作称为流(Stream)

由于异构计算的硬件特性,CUDA中以下操作是相互独立的,通过编程,是可以操作他们并发地执行的:

  • 主机端上的计算
  • 设备端的计算(核函数)
  • 数据从主机和设备间相互拷贝
  • 数据从设备内拷贝或转移
  • 数据从多个GPU设备间拷贝或转移

在这里插入图片描述

针对这种互相独立的硬件架构,CUDA使用多流作为一种高并发的方案:把一个大任务中的上述几部分拆分开,放到多个流中,每次只对一部分数据进行拷贝、计算和回写,并把这个流程做成流水线。因为数据拷贝不占用计算资源,计算不占用数据拷贝的总线(Bus)资源,因此计算和数据拷贝完全可以并发执行。如图所示,将数据拷贝和函数计算重叠起来的,形成流水线,能获得非常大的性能提升。实际上,流水线作业的思想被广泛应用于CPU和GPU等计算机芯片设计上,以加速程序。

在这里插入图片描述

以向量加法为例,上图中第一行的Stream 0部分是我们之前的逻辑,没有使用多流技术,程序的三大步骤是顺序执行的:先从主机拷贝初始化数据到设备(Host To Device);在设备上执行核函数(Kernel);将计

### Numba简介 Numba是一款能够显著提升Python程序效率的加速工具[^1]。通过即时编译技术(JIT),Numba可以将Python代码转换成机器码,在不影响可读性的前提下极大提高执行速度。 #### JIT装饰器的作用 `@jit` 装饰器用于标记需要优化的函数,其名称来源于“Just-In-Time”,意味着这些被标注的方法会在首次调用时自动完成编译过程并缓存结果以便后续快速访问[^4]。对于追求极致效能的情况,推荐设置 `nopython=True` 参数来启用无Python层模式;此时整个运算程完全绕过了CPython解释器而直接由LLVM负责底层实现[@njit](https://numba.pydata.org/numba-doc/latest/user/jit.html),从而达到最优表现。 ```python from numba import jit, njit # 基础版本 @jit def func(x): return x * 2 # 推荐使用的高性能版本 @njit def fast_func(x): return x * 2 ``` #### 应用场景 当面对涉及大量数值计算的任务——特别是那些频繁运用NumPy库内数据结构以及存在嵌套循环逻辑的情形时,引入Numba往往能带来立竿见影的速度改善效果[^2]。不过需要注意的是,并不是所有的Python特性都受到良好支持,比如复杂的控制语句或是依赖于动态特性的部分可能无法正常工作或者引发错误警告[^3]。 #### 实际案例分析 下面给出一个具体的例子展示如何利用Numba加速特定算法: 假设有一个寻找最大概率类别的需求,原始方案如下所示: ```python import numpy as np a = np.array(np.random.randint(0, 1100, (1500,)), dtype=np.str_) b = np.array(np.random.randint(0, 1100, (1500,)), dtype=np.float64) def get_max_ratio(keys, values): idx = np.argmax(values) sum_ = np.sum(values) return keys[idx], values[idx] / sum_ %timeit get_max_ratio(a,b) # 测量未优化前的时间消耗 ``` 经过适当调整后应用Numba进行优化: ```python from numba import njit @njit("Tuple((unicode_type,float64))(array(dtype=unicode_type, ndim=1), array(dtype=float64, ndim=1))", cache=True) def optimized_get_max_ratio(keys, values): max_idx = 0 total_sum = 0. for i in range(len(values)): value = float(values[i]) key_str = str(keys[i]) if i == 0 or value > values[max_idx]: max_idx = i total_sum += value result_key = str(keys[max_idx]) ratio = float(values[max_idx]) / total_sum if total_sum != 0 else 0. from numba.types import unicode_type return tuple([result_key, ratio]) %timeit optimized_get_max_ratio(a.astype(str), b) # 对比优化后的性能差异 ``` 在这个改进版里不仅加入了类型提示以帮助更快地完成编译阶段的工作,而且还替换了原有的某些操作使得它们更适合在低级环境中被执行,最终实现了更好的时间复杂度。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值