python - Numba - nopython 模式比对象模式慢?

标签 python numba

首先在这里使用 Numba。我读到 nopython 模式应该产生更快的代码,但是这个:

@jit(float64[:](int64[:], int64, float64), nopython=True)
def epsilon_bound(l, k, delta):
    return l/k+np.sqrt(np.log(1/delta))*np.sqrt(1/(2*k))

@jit(float64(float64, int64, float64), nopython=False)
def sim_bin(epsilon, sims, delta):
    k=10000
    s = np.random.binomial(k, epsilon, size=(sims,))
    print(nb.typeof(s))
    bound = epsilon_bound(s, k, delta)
    violations = np.greater(epsilon, bound)
    return np.sum(violations)/float(sims)

%%time
a = sim_bin(0.1, 1_000_000, 0.1)

运行得更快:

array(int64, 1d, C)
CPU times: user 66.7 ms, sys: 0 ns, total: 66.7 ms
Wall time: 65.7 ms

比这个:

@jit(float64[:](int64[:], int64, float64), nopython=True)
def epsilon_bound(l, k, delta):
    return l/k+np.sqrt(np.log(1/delta))*np.sqrt(1/(2*k))

@jit(float64(float64, int64, float64), nopython=True)
def sim_bin(epsilon, sims, delta):
    k=10000
    s = np.random.binomial(k, epsilon, size=(sims,))
    #print(nb.typeof(s))
    bound = epsilon_bound(s, k, delta)
    violations = np.greater(epsilon, bound)
    return np.sum(violations)/float(sims)

CPU times: user 4.94 s, sys: 8.02 ms, total: 4.95 s
Wall time: 4.93 s

运行 sim_bin.inspect_types() 显示第一个选项使用所有 pyobjects,而第二个选项正确推断所有类型。根据文档 ( http://numba.pydata.org/numba-doc/0.31.0/glossary.html#term-nopython-mode ) nopython 模式应该产生更快的代码。 有谁知道发生了什么事?一定有充分的理由,但我是使用 Numba 的新手。是因为我主要使用矢量化 numpy 函数吗?

谢谢!!

最佳答案

函数的一个主要瓶颈(至少对于 numba 0.31,windows 10)似乎是 np.random.binomial 调用。当我测试它时:

@jit(nopython=True)
def nbbinom():
    return np.random.binomial(10000, 0.1, size=(1000000,))

nbbinom() # warmup
%timeit nbbinom()
# 1 loop, best of 3: 2.45 s per loop
%timeit np.random.binomial(10000, 0.1, size=(1000000,))
# 10 loops, best of 3: 23.1 ms per loop

但这可能取决于 numba 版本。 Numba(不幸的是)经常遭受性能退化的困扰,而这些性能退化(幸运的是)很快就得到了修复。可能它只需要在他们的错误跟踪器上有一个问题(如果它尚未修复)。

但即便如此,您的代码仍包含大量矢量化操作。如果您使用矢量化操作,您不会通过 numba 获得太多速度提升。作为一个经验法则:如果你已经可以在不使用 python 循环的情况下使用 numpy 来完成它,你就不需要 numba(也有异常(exception)。例如:我发现 numba 对于小数组来说肯定更快,其中numpy-ufuncs 有很大的开销)。

另一件事是创建随机数组比实际操作花费的时间长得多(在 numpy 和 numba 中):

import numpy as np
from numba import njit

@njit
def epsilon_bound1(l, k, delta):
    return l/k+np.sqrt(np.log(1/delta))*np.sqrt(1/(2*k))

def epsilon_bound2(l, k, delta):
    return l/k+np.sqrt(np.log(1/delta))*np.sqrt(1/(2*k))

def sim_bin(s, k, epsilon, sims, delta, func):
    bound = func(s, k, delta)
    violations = np.greater(epsilon, bound)
    return np.sum(violations)/float(sims)

epsilon = 0.1
sims = 1000000
delta = 0.1
k=10000
s = np.random.binomial(k, epsilon, size=(sims,))
%timeit np.random.binomial(k, epsilon, size=(sims,))
# 1 loop, best of 3: 232 ms per loop

sim_bin(s, k, 0.1, 1000000, 0.1, epsilon_bound1)  # warmup
%timeit sim_bin(s, k, 0.1, 1000000, 0.1, epsilon_bound1)
# 10 loops, best of 3: 28.5 ms per loop
%timeit sim_bin(s, k, 0.1, 1000000, 0.1, epsilon_bound2)
# 10 loops, best of 3: 37.6 ms per loop

因此,当您对 sim_bin 进行基准测试时,您实际上只对对 np.random.binomial 的调用进行基准测试,无论是相对较快的 numpy 还是(当前)相当慢的 numba 实现.

关于python - Numba - nopython 模式比对象模式慢?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42846313/

相关文章:

python - Ultisnips python 插值片段,从文件名中提取数字

python - 想要在 X 和 O 之间交替

python - 数字错误 "sequence item 0: expected str instance, type found"

python - python3.1中的sgml解析

python - 在 python boto 中使用 cognito 获取 AWS 凭证

Python 在对相同对象执行相同操作两次时给出了两个不同的结果

python - 在 Numba 中关闭列表反射

python - 使用 Python 进行高效、大规模的竞赛评分

python - 使用 numba 提供显式类型时,njit 编译期间出现输入错误

python - Numba:使用具有默认值的参数调用具有显式签名的 jit