python - 分配给数组时 Numba 很慢?

标签 python arrays numba

Numba 似乎是加速数字代码执行的绝佳解决方案。但是,当对数组进行赋值时,Numba 似乎比标准 Python 代码慢。考虑这个例子比较四个备选方案,使用/不使用 Numba,写入数组/标量:

(计算有意保持非常简单,以关注问题,即对标量的赋值与对数组单元格的赋值)

@autojit
def fast_sum_arr(arr):
    z = arr.copy()
    M = len(arr)
    for i in range(M):
        z[i] += arr[i]

    return z

def sum_arr(arr):
    z = arr.copy()
    M = len(arr)
    for i in range(M):
        z[i] += arr[i]

    return z

@autojit
def fast_sum_sclr(arr):
    z = 0
    M = len(arr)
    for i in range(M):
        z += arr[i]

    return z

def sum_sclr(arr):
    z = 0
    M = len(arr)
    for i in range(M):
        z += arr[i]

    return z

使用 IPython 的 %timeit 来评估我得到的四个备选方案:

In [125]: %timeit fast_sum_arr(arr)
100 loops, best of 3: 10.8 ms per loop

In [126]: %timeit sum_arr(arr)
100 loops, best of 3: 4.11 ms per loop

In [127]: %timeit fast_sum_sclr(arr)
100000 loops, best of 3: 10 us per loop

In [128]: %timeit sum_sclr(arr)
100 loops, best of 3: 2.93 ms per loop

sum_arr,不是用 Numba 编译的,比用 Numba 编译的 fast_sum_arr 快两倍多。另一方面,使用 Numba 编译的 fast_sum_sclr 比未使用 Numba 编译的 sum_sclr 快两个数量级以上。

所以 Numba 在加速 sum_sclr 的任务上表现得非常好,但实际上会使 sum_arr 执行得更慢。 sum_sclr 和 sum_arr 之间的唯一区别是前者分配给标量,而后者分配给数组单元格。

不知道有没有关系,最近在博客上看了下面的http://www.phi-node.com/ :

“事实证明,当 Numba 遇到它不直接支持的任何构造时,它会切换到(非常)慢的代码路径。”

博客作者使用 if 语句而不是 Python 的 max() 使 Numba 执行得更快。

对此有何见解?

谢谢,

全能

最佳答案

这里慢的是 arr.copy() 函数,而不是对数组的写访问。证明:

# -*- coding: utf-8 -*-
from numba import autojit
from Timer import Timer
import numpy as np

@autojit
def fast_sum_arr(arr, z):
    #z = arr.copy()
    M = len(arr)
    for i in range(M):
        z[i] += arr[i]

    return z

def sum_arr(arr, z):
    #z = arr.copy()
    M = len(arr)
    for i in range(M):
        z[i] += arr[i]

    return z

@autojit
def fast_sum_sclr(arr):
    z = 0
    M = len(arr)
    for i in range(M):
        z += arr[i]

    return z

def sum_sclr(arr):
    z = 0
    M = len(arr)
    for i in range(M):
        z += arr[i]

    return z

if __name__ == '__main__':
    vec1 = np.ones(1000)
    z = vec1.copy()
    with Timer() as t0:
        for i in range(10000):
            pass
    print "time for empty loop ", t0.secs
    print
    with Timer() as t1:
        for i in range(10000):
            sum_arr(vec1, z)
    print "time for sum_arr  [µs]:   ", (t1.secs-t0.secs)  / 10000 * 1e6
    with Timer() as t1:
        for i in range(10000):
            fast_sum_arr(vec1, z)
    print "time for fast_sum_arr  [µs]:   ", (t1.secs-t0.secs)  / 10000 * 1e6
    with Timer() as t1:
        for i in range(10000):
            sum_sclr(vec1)
    print "time for sum_arr  [µs]:   ", (t1.secs-t0.secs)  / 10000 * 1e6
    with Timer() as t1:
        for i in range(10000):
            fast_sum_sclr(vec1)
    print "time for fast_sum_arr  [µs]:   ", (t1.secs-t0.secs)  / 10000 * 1e6

"""
time for empty loop  0.000312089920044

time for sum_arr       [µs]:    432.02688694
time for fast_sum_arr  [µs]:      7.43598937988
time for sum_arr       [µs]:    284.574580193
time for fast_sum_arr  [µs]:      5.74610233307
"""

关于python - 分配给数组时 Numba 很慢?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18071285/

相关文章:

python - 鼠尾草中的 3D 散点图

python - 如何在 Keras 中使用 model.predict() 重现 model.evaluate() 输出

python - 除周末 Python 之外的日期时间序列

ios - 重置保存的 map 图钉,iOS Swift

python - 当类的属性包含另一个类实例时如何指定 numba jitclass?

python - 如何从不完整的字典中替换 python 中字符串中的命名变量?

arrays - 在 VBA 中创建和转置数组

c++ - 二维数组的段错误

python - 快速生成大规模随机ndarray的方法

python - 为什么 numba 和 numpy 在就地操作上表现不同?