为什么要根据速度使用numpy over list?

时间:2017-10-21 07:16:34

标签: python arrays numpy

参考Why NumPy instead of Python lists?

tom10说:

  

速度:这是对列表和NumPy数组进行求和的测试,显示NumPy数组上的总和快10倍(在此测试中 - 里程可能会有所不同)。

但我的测试使用以下代码:

import numpy as np
import time as time

N = 100000

#using numpy
start = time.time()
array = np.array([])

for i in range(N):
    array = np.append(array, i)

end = time.time()
print ("Using numpy: ", round(end-start, 2), end="\n")

#using list
start = time.time()
list = []

for i in range(N):
    list.append(i)

list = np.array(list)   
end = time.time()
print ("Using list : ", round(end-start, 2), end="\n")

给出结果:

Using numpy: 8.35
Using list : 0.02

当使用“追加”时,列表优于numpy?

1 个答案:

答案 0 :(得分:1)

回答你的问题,是的。附加到数组是一项昂贵的操作,而列表使其相对便宜(请参阅Internals of Python list, access and resizing runtimes了解原因)。但是,没有理由放弃numpy。还有其他方法可以轻松地将数据添加到numpy数组中。

令人惊讶的是(对我来说,无论如何)有多少方法可以做到这一点。跳到底部查看每个基准测试的基准。

可能最常见的是简单地预先分配数组,并将其编入索引,

$position

当然,您也可以为列表预先分配内存,因此请将其包含在基准比较中。

#using preallocated numpy
start = time.time()
array = np.zeros(N)

for i in range(N):
    array[i] = i

end = time.time()
print ("Using preallocated numpy: ", round(end-start, 5), end="\n")

根据你的代码,使用numpy的#using preallocated list start = time.time() res = [None]*N for i in range(N): res[i] = i res = np.array(res) end = time.time() print ("Using preallocated list : ", round(end-start, 5), end="\n") 函数也可能会有所帮助,该函数使用迭代器的结果来初始化数组。

fromiter

当然,使用内置迭代器并不是非常灵活,所以让我们尝试一下自定义迭代器,

#using numpy fromiter shortcut
start = time.time()

res = np.fromiter(range(N), dtype='float64') # Use same dtype as other tests

end = time.time()
print ("Using fromiter : ", round(end-start, 5), end="\n")

这是使用#using custom iterator start = time.time() def it(N): i = 0 while i < N: yield i i += 1 res = np.fromiter(it(N), dtype='float64') # Use same dtype as other tests end = time.time() print ("Using custom iterator : ", round(end-start, 5), end="\n") 的两种非常灵活的方式。第一种是使用预分配阵列,是最灵活的。让我们看看他们如何比较:

numpy

关闭,您可以看到预分配使Using numpy: 2.40017 Using list : 0.0164 Using preallocated numpy: 0.01604 Using preallocated list : 0.01322 Using fromiter : 0.00577 Using custom iterator : 0.01458 比使用列表快得多,尽管预分配列表会使两者的速度大致相同。尽管迭代器性能很好,但使用内置迭代器非常快 当使用自定义迭代器时,回退到预分配数组的范围内并列出。

将代码直接转换为numpy的效果通常不如numpy。使用append方法找到方法几乎总能带来实质性的改进。在这种情况下,预先分配数组或将每个元素的计算表示为迭代器,以获得与python列表类似的性能。或者使用vanilla python列表,因为性能大致相同。

编辑:原始答案还包括numpy。这被删除,因为它不适合一次添加一个元素的用例,np.fromfunction实际初始化数组并使用fromfunction的广播进行单个函数调用。它快了大约一百倍,所以如果你能用广播来解决你的问题,请不要理会这些其他方法。