在Python中,array.count()的数量级是否比list.count()慢几个?
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了在Python中,array.count()的数量级是否比list.count()慢几个?相关的知识,希望对你有一定的参考价值。
目前我正在玩Python性能,试图加速我的程序(通常是计算启发式的程序)。我总是使用列表,试图不进入numpy
数组。
但最近我听说Python有8.7. array — Efficient arrays of numeric values
,所以我想我会尝试那个。
我写了一段代码来测量array.count()
与list.count()
,因为我在我的代码中的许多地方使用它:
from timeit import timeit
import array
a = array.array('i', range(10000))
l = [range(10000)]
def lst():
return l.count(0)
def arr():
return a.count(0)
print(timeit('lst()', "from __main__ import lst", number=100000))
print(timeit('arr()', "from __main__ import arr", number=100000))
使用array
时,我期待性能略有提升。嗯,这就是发生的事情:
> python main.py
0.03699162653848456
74.46420751473268
因此,根据timeit
,list.count()
比array.count()
快2013倍。我绝对没想到。所以我搜索了SO,python docs等,我发现的唯一的事情就是数组中的对象必须首先包装到int
-s中,所以这可能会减慢速度,但我希望在创建时能够实现这一点一个array.array
实例,而不是随机访问它(我相信是.count()
所做的)。
捕获量在哪里?
难道我做错了什么?
或者我可能不应该使用标准数组并直接进入numpy.array
s?
捕获的地方在哪里?
如上所述,初始测试并不比较苹果与苹果:
没有提到python-2.7,其中range()
确实创建了一个RAM分配的数据结构,而xrange()
类似于python-3重新制定的对象(如下所示)生成器 - 永远不会与任何智能RAM分配的数据结构相比。
>>> L_above_InCACHE_computing = [ range( int( 1E24 ) ) ] # list is created
>>> L_above_InCACHE_computing.count( 0 ) # list has no 0 in
0
>>> L_above_InCACHE_computing.count( range( int( 1E24 ) ) )# list has this in
1
生成器的对象内在.__len__()
吐出长度,仍然没有计数发生,是吗? (很高兴它没有,它甚至不适合RAM的~ 10^20 [TB]
......,但它可以“生活”在py3 +作为对象)
>>> print( L[0].__doc__ )
range(stop) -> range object
range(start, stop[, step]) -> range object
Return an object that produces a sequence of integers from start (inclusive)
to stop (exclusive) by step. range(i, j) produces i, i+1, i+2, ..., j-1.
start defaults to 0, and stop is omitted! range(4) produces 0, 1, 2, 3.
These are exactly the valid indices for a list of 4 elements.
When step is given, it specifies the increment (or decrement).
定量公平测试?需要更好的测试工程细节:
远远超过几十MB,以避免InCACHE计算工件的错误期望,这些工件永远不会扩展到现实世界的问题大小:
>>> L_above_InCACHE_computing = [ range( int( 1E24 ) ) ]
>>> L_above_InCACHE_computing[0]
range(0, 999999999999999983222784)
>>> print( L_above_InCACHE_computing[0].__len__() )
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
OverflowError: Python int too large to convert to C ssize_t
进入RAM可行,但高于InCACHE-horizon sizings:
# L_aRunABLE_above_InCACHE_computing = [ range( int( 1E9 ) ) ] # ~8+GB ->array
# would have no sense to test
# a benchmark on an array.array().count( something ) within an InCACHE horizon
直接去
numpy
阵列?
绝对是一个明智的步骤来测试。矢量化内部性可能会令人惊讶,并且通常会做很多事情:o)
如果numpy-strength甚至可以提升你的代码库的其他部分,那么在很大程度上取决于你的其他代码。最后但同样重要的是,要注意过早的优化和扩展。一些[TIME]
-domain陷阱可以应对,如果可以在[SPACE]
域中花费更多,但最危险的是丢失InCACHE-locality,其中没有权衡可能有帮助。因此,最好不要过早锁定有前景的细节,但要以失去全球规模的绩效目标为代价。
以上是关于在Python中,array.count()的数量级是否比list.count()慢几个?的主要内容,如果未能解决你的问题,请参考以下文章
array_count_values — 统计数组中所有的值
array_count_values — 统计数组中所有的值
Swift array.capacity vs array.count