Python 提速大杀器之 numba 篇

你是不是曾经有这样的苦恼,python 真的太好用了,但是它真的好慢啊(哭死) ; C++ 很快,但是真的好难写啊,此生能不碰它就不碰它。老天啊,有没有什么两全其美的办法呢?俗话说的好:办法总是比困难多,大家都有这个问题,自然也就有大佬来试着解决这个问题,这就请出我们今天的主角: numba


每次一个Python小技巧!

不过在介绍 numba 之前,我们还是得来看看 python 为什么这么慢:

为什么 python 这么慢

用过 python 的人都知道, 尤其是在有循环的情况下,python 会比 C++ 慢很多,所以很多人都避免在 python 代码里引入复杂的 for 循环。我们可以想想 python 和 C++ 写起来有哪些区别呢:

动态变量

如果你写过 C/C++ 就会发现,我们需要对变量类型有严格的定义,我们需要定义变量的类型是 int 或者 float 之类的。但是 python 就不一样了,写过的 python 的人都知道,它去掉了变量申明和数据类型。也就是说,无论啥数据,咱啥都不用管,想存就存!那么 python 是如何做到这样洒脱自由的呢?这就不得不提 python 中万物皆是对象了,真正的数据是存在对象里面的。对于一个简单的两个变量的加法,python 每次在做运算的时候都得先判断变量的类型,再取出来进行运算,而对于 C 来说,简单的内存读写和机器指令 ADD 即可。其实在 C/C++ 中也有可变数据类型,但是其声明是非常复杂的,是一种非常令人头疼的结构。

解释性语言

C/C++ 这类编译性语言最大的好处就是其编译过程是发生在运行之前的,源代码在调用前被编译器转换为可执行机器码,这样就节约了大量的时间。而 python 作为一种解释性语言,没法做到一次编译,后续可以直接运行,每次运行的时候都要重新将源代码通过解释器转化为机器码。这样一个好处就是非常容易 debug( 这里要再次感叹一下 python 真不愧是新手友好型语言~), 当然,这个问题自然也是有尝试解决的办法,一个很重要的技术就是 JIT (Just-in-time compilation):JIT 即时编译技术是在运行时(runtime)将调用的函数或程序段编译成机器码载入内存,以加快程序的执行。说白了,就是在第一遍执行一段代码前,先执行编译动作,然后执行编译后的代码。

上面只是简单列出了两点,当然还有更多的原因,限于篇幅就不再具体介绍,而我们开篇提到的 numba 就是通过 JIT 加速了 python 代码。那么怎么使用 numba 加速我们的代码呢?我们可以看一些简单的例子:

numba 加速 python 的小例子

用 numba 加速 python 代码多简单方便呢,我们先来看看如何使用 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 

当需要计算的矩阵很小的时候,貌似速度也不慢,可以接受,但是如果输入的矩阵大小为 (500, 500),

a = np.random.random((500, 500)) 
%timeit cal_sum(a) 

输出结果为:

47.8 ms ± 499 µs per loop (mean ± std. dev. of 7 runs, 10 loops each) 

我们尝试加上 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 

输入同样大小的矩阵

a = np.random.random((500, 500)) 
%timeit cal_sum(a) 

输出结果为:

236 µs ± 545 ns per loop (mean ± std. dev. of 7 runs, 1000 loops each) 

注意在这里我们使用了 %itemit 测试运行时间(原因我们留到后面说),通过对比两个时间,我们可以发现通过 numba 获得了非常明显的加速效果!

  • 12
    点赞
  • 75
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值