Numpy对于基本阵列操作非常慢

时间:2019-04-08 12:09:25

标签: arrays python-3.x list numpy

我有一个代码,其中我对一堆是多个数组的数字数据进行了许多基本的算术计算。我已经意识到,在大多数可想象的操作中,numpy类始终比默认的python慢​​。为什么会这样?

例如,我有一个简单的代码片段,其中我所做的只是用另一个numpy数组中检索的另一个更新1 numpy数组元素,或者用其他2个numpy数组元素的数学乘积更新了它。这应该是一项基本操作,但始终比我用list进行时至少慢2-3倍。

首先,我认为这是因为我尚未统一数据结构,并且编译器必须进行许多不必要的转换。因此,我重新编码了整个内容,并用float替换了每个numpy.float64,并用list替换了每个numpy.ndarray,整个代码中的整个数据都是numpy.float64,所以不必进行任何不必要的转换。

与我仅使用listfloat相比,该代码仍然慢2-3倍。

例如:

    ALPHA       = [[random.uniform(*a_param)    for k in range(l2)] for l in range(l1)]
    COEFF       = [[random.uniform(*c_param)    for k in range(l2)] for l in range(l1)]

    summa=0.0
    for l in range(l1):
        for k in range(l2):
            summa+=COEFF[l][k] * ALPHA[l][k]

始终比以下速度快2-3倍:

    ALPHA       = numpy.random.uniform(*a_param, (l1,l2))
    COEFF       = numpy.random.uniform(*c_param, (l1,l2))

    summa=0.0
    for l in range(l1):
        for k in range(l2):
            summa+=COEFF[l][k] * ALPHA[l][k]

这是怎么可能的,我做错了什么吗,因为numpy应该可以加快速度。

我正在使用Python 3.5.3numpy (1.12.1)作记录,我应该更新吗?

2 个答案:

答案 0 :(得分:1)

修改NumPy数组的单个元素预计不会比修改Python列表的单个元素更快。当您在整个数组(或数组的子集)上执行“向量化”操作时,使用NumPy的速度就会加快。尝试将NumPy数组的前10000个元素分配为与另一个数组的前10000个元素相等,然后与使用列表进行比较。

如果您的数据和/或操作非常小(一个或几个元素),那么最好不使用NumPy。

答案 1 :(得分:0)

我尝试了两件事:

  1. 运行您的两个代码块。对我来说,它们的速度差不多。
  2. 编写一个新函数,利用numpy的矢量化数学。这比其他方法快几倍。

这是我的功能:

import numpy as np

def with_lists(l1, l2):
    ALPHA = [[random.uniform(0, 1) for k in range(l2)] for l in range(l1)]
    COEFF = [[random.uniform(0, 1) for k in range(l2)] for l in range(l1)]
    summa=0.0
    for l in range(l1):
        for k in range(l2):
            summa+=COEFF[l][k] * ALPHA[l][k]
    return summa

def with_arrays(l1, l2):
    ALPHA = np.random.uniform(size=(l1,l2))
    COEFF = np.random.uniform(size=(l1,l2))
    summa=0.0
    for l in range(l1):
        for k in range(l2):
            summa+=COEFF[l][k] * ALPHA[l][k]
    return summa

def with_ufunc(l1, l2):
    """Avoid the loop completely by exploitng numpy's
    elementwise math."""
    ALPHA = np.random.uniform(size=(l1,l2))
    COEFF = np.random.uniform(size=(l1,l2))
    return np.sum(COEFF * ALPHA)

当我比较速度(我在IPython中使用%timeit魔术)时,得到以下信息:

>>> %timeit with_lists(10, 10)
107 µs ± 4.7 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)

>>> %timeit with_arrays(10, 10)
91.9 µs ± 10.5 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)

>>> %timeit with_ufunc(10, 10)
12.6 µs ± 589 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

第三个函数(无循环)在我的计算机上的速度大约是10到30倍,具体取决于l1l2的值。