繁体   English   中英

Numpy 数组索引和/或添加似乎很慢

[英]Numpy array indexing and/or addition seems slow

我正在尝试对 numpy 数组进行基准测试,因为当我尝试在脚本中用 numpy 数组替换 python 数组时,结果比预期的要慢。

我知道我错过了一些东西,我希望有人能澄清我的无知。

我创建了两个函数并对它们计时

NUM_ITERATIONS = 1000

def np_array_addition():
    np_array = np.array([1, 2])
    for x in xrange(NUM_ITERATIONS):
        np_array[0] += x
        np_array[1] += x


def py_array_addition():
    py_array = [1, 2]
    for x in xrange(NUM_ITERATIONS):
        py_array[0] += x
        py_array[1] += x

结果:

np_array_addition: 2.556 seconds
py_array_addition: 0.204 seconds

是什么赋予了? 是什么导致了大规模放缓? 我想如果我使用静态大小的数组 numpy 至少会具有相同的速度。

谢谢!

更新:

numpy 数组访问速度缓慢一直困扰着我,我想“嘿,它们只是内存中的数组,对吗?Cython 应该解决这个问题!”

它做到了。 这是我修改后的基准

import numpy as np
cimport numpy as np    

ctypedef np.int_t DTYPE_t    


NUM_ITERATIONS = 200000
def np_array_assignment():
    cdef np.ndarray[DTYPE_t, ndim=1] np_array = np.array([1, 2])
    for x in xrange(NUM_ITERATIONS):
        np_array[0] += 1
        np_array[1] += 1    


def py_array_assignment():
    py_array = [1, 2]
    for x in xrange(NUM_ITERATIONS):
        py_array[0] += 1
        py_array[1] += 1

我将np_array重新定义为cdef np.ndarray[DTYPE_t, ndim=1]

print(timeit(py_array_assignment, number=3))
# 0.03459
print(timeit(np_array_assignment, number=3))
# 0.00755

那是python函数也被cython优化了。 纯python中python函数的时间是

print(timeit(py_array_assignment, number=3))
# 0.12510

17 倍加速。 当然,这是一个愚蠢的例子,但我认为这是有教育意义的。

这不是(只是)缓慢的加法,它是元素访问开销,参见示例:

def np_array_assignment():
    np_array = np.array([1, 2])
    for x in xrange(NUM_ITERATIONS):
        np_array[0] = 1
        np_array[1] = 1


def py_array_assignment():
    py_array = [1, 2]
    for x in xrange(NUM_ITERATIONS):
        py_array[0] = 1
        py_array[1] = 1

timeit np_array_assignment()
10000 loops, best of 3: 178 us per loop

timeit py_array_assignment()
10000 loops, best of 3: 72.5 us per loop

当一次对整个结构执行时,Numpy 对向量(矩阵)的操作速度很快。 这种逐个元素的操作很慢。

使用 numpy 函数避免循环,一次对整个数组进行操作,即:

def np_array_addition_good():
    np_array = np.array([1, 2])
    np_array += np.sum(np.arange(NUM_ITERATIONS))

将您的功能与上述功能进行比较的结果非常具有启发性:

timeit np_array_addition()
1000 loops, best of 3: 1.32 ms per loop

timeit py_array_addition()
10000 loops, best of 3: 101 us per loop

timeit np_array_addition_good()
100000 loops, best of 3: 11 us per loop

但实际上,如果你折叠循环,你可以用纯 python 做同样的事情:

def py_array_addition_good():
        py_array = [1, 2]
        rangesum = sum(range(NUM_ITERATIONS))
        py_array = [x + rangesum for x in py_array]

timeit py_array_addition_good()
100000 loops, best of 3: 11 us per loop

总而言之,通过如此简单的操作,使用 numpy 确实没有任何改进。 纯 python 中的优化代码同样有效。


有很多关于它的问题,我建议在那里查看一些好的答案:

如何使用 numpy 数组最大限度地提高效率?

numpy float:比内置算术运算慢 10 倍?

如果你在 python 中执行循环,你实际上并没有使用 numpy 的向量化数组加法; 还有@shashkello 提到的访问开销。

我冒昧地稍微增加了数组大小,并添加了一个矢量化版本的加法:

import numpy as np
from timeit import timeit

NUM_ITERATIONS = 1000

def np_array_addition():
    np_array = np.array(xrange(1000))
    for x in xrange(NUM_ITERATIONS):
        for i in xrange(len(np_array)):
            np_array[i] += x

def np_array_addition2():
    np_array = np.array(xrange(1000))
    for x in xrange(NUM_ITERATIONS):
        np_array += x

def py_array_addition():
    py_array = range(1000)
    for x in xrange(NUM_ITERATIONS):
        for i in xrange(len(py_array)):
            py_array[i] += x

print timeit(np_array_addition, number=3)  # 4.216162
print timeit(np_array_addition2, number=3) # 0.117681
print timeit(py_array_addition, number=3)  # 0.439957

如您所见,矢量化的 numpy 版本非常容易获胜。 随着数组大小和/或迭代的增加,差距只会变得更大。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM