Numba:什么时候使用 nopython=True?

Numba: when to use nopython=True?

我有以下设置:

import numpy as np
import matplotlib.pyplot as plt
import timeit
import numba
@numba.jit(nopython=True, cache=True)
def f(x):
    summ = 0
    for i in x:
        summ += i
    return summ

@numba.jit(nopython=True)
def g21(N, locs):
    rvs = np.random.normal(loc=locs, scale=locs, size=N)
    res = f(rvs)
    return res

@numba.jit(nopython=False)
def g22(N, locs):
    rvs = np.random.normal(loc=locs, scale=locs, size=N)
    res = f(rvs)
    return res

g22g21 是完全相同的功能,只是其中一个具有 nopython=True 而另一个具有 nopython=False

现在我给他们一个输入。如果 locs 是一个标量,那么 numba 应该能够编译所有东西,因为它们支持 numpy.random.normal() 和这个签名。然而,如果 locs 是一个数组,numba 不支持这个签名,应该返回到 python 解释器。

我运行这个首先只是为了编译函数

N = 10_000

g22(N, 3)
g22(N, np.linspace(0,1,N))
g21(N, 3)
# g21(N, np.linspace(0,1,N))  # returns an error

现在我运行一个速度比较

%timeit g21(N, 3)
%timeit g22(N, 3)
%timeit g22(N, np.linspace(0,1,N))

哪个returns

274 µs ± 3.43 µs per loop (mean ± std. dev. of 7 runs, 1,000 loops each)
270 µs ± 5.38 µs per loop (mean ± std. dev. of 7 runs, 1,000 loops each)
421 µs ± 54.3 µs per loop (mean ± std. dev. of 7 runs, 1,000 loops each)

g22(N, np.linspace(0,1,N) 是最慢的,因为它返回到 python 解释器。

然而我不明白的是 g21(N, 3)g22(N, 3) 的速度大致相同,即使一个有 nopython=True 而另一个没有。

但是 g22(N,3) 有一个很大的优势,它可以接受另一个参数,即 g22(N, np.linspace(0,1,N)),所以它更通用,但同时没有 [=18= 的速度损失]

所以我的问题是:

  1. 在这种情况下,使用nopython=True有什么用,如果nopython=False的函数达到相同的速度?

  2. 在哪种情况下 nopython=Truenopython=False 好?

编辑:这个答案是错误的,请参阅下面的评论并改为阅读已接受的答案


好吧,我继续使用 nopython=False,这似乎导致了更多的编译。这不是很科学的分析,但似乎我的函数有时会在我更改各种参数时重新编译,而使用 nopython=True 它一旦编译就再也没有重新编译过。所以这似乎是一个潜在的差异

  1. in this case, what is the use of using nopython=True, if a function with nopython=False achieves same speed?
  2. in which specific case is nopython=True better than nopython=False?

documentation 状态:

Numba has two compilation modes: nopython mode and object mode. The former produces much faster code, but has limitations that can force Numba to fall back to the latter. To prevent Numba from falling back, and instead raise an error, pass nopython=True.

请注意,在 Numba 中,将尝试在 两种模式 中将代码编译为本机二进制文件。但是,nopython 在不可能时会产生错误,而另一个会产生警告并导致使用回退代码。

对于某些应用程序,性能可能很关键,因此您确实不希望调用回退代码。例如,high-performance 应用程序 就是这种情况。在这种情况下出现错误比在昂贵的机器(如超级计算机或计算服务器)上运行几天而不是几分钟的代码要好。由于功能不受支持,使用不同版本的 Numba 可能会悄悄地导致某些机器上的回退。我个人总是使用 nopython 模式来防止这种情况(因为回退代码通常太慢而没有用)并且我认为对象模式有点无用。简而言之,nopython 提供更强的性能保证