我注意到通过“直接”迭代通过numpy数组迭代通过tolist
方法迭代之间有意义的区别。见下面定时:什么是迭代通过一个numpy数组最快的方法
直接
[i for i in np.arange(10000000)]
经由tolist
[i for i in np.arange(10000000).tolist()]
考虑到我发现了一种更快的方法。我想问问还有什么可以让它变得更快?
什么是最快的方式来遍历一个numpy数组?
我注意到通过“直接”迭代通过numpy数组迭代通过tolist
方法迭代之间有意义的区别。见下面定时:什么是迭代通过一个numpy数组最快的方法
直接
[i for i in np.arange(10000000)]
经由tolist
[i for i in np.arange(10000000).tolist()]
考虑到我发现了一种更快的方法。我想问问还有什么可以让它变得更快?
什么是最快的方式来遍历一个numpy数组?
这些都是我的机器慢
In [1034]: timeit [i for i in np.arange(10000000)]
1 loop, best of 3: 2.16 s per loop
上计时,如果我直接生成的范围(PY3所以这是一个genertor)倍要好得多。以此为基础来理解这个尺寸的列表。
In [1035]: timeit [i for i in range(10000000)]
1 loop, best of 3: 1.26 s per loop
tolist
首先将arange转换为列表;需要更长的时间,但迭代仍然是一个列表
In [1036]: timeit [i for i in np.arange(10000000).tolist()]
1 loop, best of 3: 1.6 s per loop
使用list()
上 - 同时在阵列上直接迭代;这表明直接迭代首先执行此操作。
In [1037]: timeit [i for i in list(np.arange(10000000))]
1 loop, best of 3: 2.18 s per loop
In [1038]: timeit np.arange(10000000).tolist()
1 loop, best of 3: 927 ms per loop
同一时间在.tolist
In [1039]: timeit list(np.arange(10000000))
1 loop, best of 3: 1.55 s per loop
一般来说,如果你必须循环迭代一个,名单上的工作速度更快。访问列表中的元素更简单。
查看索引返回的元素。
a[0]
是另一个numpy
对象;它由a
中的值构成,但不是简单的取值
list(a)[0]
是同一类型;该列表只是[a[0], a[1], a[2]]]
In [1043]: a = np.arange(3)
In [1044]: type(a[0])
Out[1044]: numpy.int32
In [1045]: ll=list(a)
In [1046]: type(ll[0])
Out[1046]: numpy.int32
但tolist
阵列成纯列表转换,在这种情况下,作为整数的列表。它比list()
做更多的工作,但它在编译代码。
In [1047]: ll=a.tolist()
In [1048]: type(ll[0])
Out[1048]: int
一般不要使用list(anarray)
。它很少做任何有用的事情,并且不如tolist()
那样强大。
迭代数组的最快方式是什么 - 无。至少不在Python中;在c代码中有快速的方法。
a.tolist()
是从数组创建列表整数的最快矢量化方法。它迭代,但在编译代码中这样做。
但是你真正的目标是什么?
感谢@hpaulj这非常接近实际回答我的问题,因为你陈述了......“什么是迭代数组的最快方法 - 无。”我可能会选择这个作为我的答案,但我会稍微打开它。 – piRSquared
这实际上并不奇怪。让我们从最慢的一个时间开始研究这些方法。
[i for i in np.arange(10000000)]
此方法要求蟒伸入numpy的阵列(存储在C存储器范围),一个元件的时间,在存储器分配Python对象,并创建一个指针列表中的该对象。每次你在存储在C后端的numpy数组之间进行管道操作并将其拉入纯python时,会产生间接费用。这种方法增加了10,000,000次的成本。
下一页:
[i for i in np.arange(10000000).tolist()]
在这种情况下,使用.tolist()
使得单个调用numpy的Ç后端和分配所有一次性的元素添加到列表中。然后您使用python遍历该列表。
最后:
list(np.arange(10000000))
这基本上做同样的事情如上,但它创造numpy的原生类型对象(例如np.int64
)的列表。使用list(np.arange(10000000))
和np.arange(10000000).tolist()
应该差不多同时。
所以,在迭代而言,使用numpy
的主要优点是你不需要进行迭代。操作以向量化的方式应用于阵列。迭代只会减慢速度。如果你发现自己迭代数组元素,你应该寻找一种方法来重构你正在尝试的算法,这种方式只使用numpy操作(它有很多内建的!),或者如果真的有必要,你可以使用np.apply_along_axis
,np.apply_over_axis
或np.vectorize
。
但是'list(np.arange(10))'和'np.arange(10).tolist()'之间存在细微的差别:第一个会导致一个“np.int64”列表的第二个Python的int列表。第一个问题可能会导致序列化等问题。使用json。 json会在第一个错误,因为它不能处理'np.int64' – MaxNoe
你是绝对正确的。 – James
这是非常有用的,这就是为什么我投了赞成票,我希望别人也这么做。我现在要解决这个问题了,因为我仍然希望看到通过数组进行迭代的其他选项。 – piRSquared
*是*奇数。我自己尝试了好几次,似乎将它转换为列表确实使其始终更快。感谢您将此带入光明中。 –
只需迭代并获取列表或做一些处理呢?使用'list(np.arange(1000000))'看起来非常快。 – Divakar
@Divakar参见http://stackoverflow.com/a/40575522/2336654 – piRSquared