我在一系列角色的随机样本中发现了这一点。如果它属于其他地方,请告诉我。
如果我生成1000个字符的列表:
my_list = random.choices('abc', k=1000)
和一个1000个字符的numpy数组:
my_array = np.array(my_list)
然后将它们连接成一个长字符串并计时,我得到:
''.join(my_list) # vanilla Python list
# 7.69 µs ± 103 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
''.join(my_array) # numpy array
# 257 µs ± 3.31 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
为什么运行时间存在巨大差异?
我的第一个想法是str.join
方法在加入之前将numpy数组转换为列表。没有这样的运气。如果我把我的numpy数组转换成一个列表,我就不会在两个操作之间找到差别。 ndarray.tolist()
非常快!
my_array.tolist()
11.6 µs ± 87 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
所以我认为str.join
只是针对Python列表进行了超级优化,而不是针对numpy数组?这看起来很奇怪,因为numpy数组和操作通常都经过了非常优化,并且通常比等效的vanilla Python实现快得多(参见下面的示例)。
我不确定在哪里找到str.join
的实际实现,所以我无法使用源代码(Luke)。
如果我用numpy生成我的随机字符:
my_array = np.random.choice([char for char in 'abc'], size=1000, replace=True)
# 29.8 µs ± 2.33 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
并将此运行时间与random.choices
进行比较,我得到的numpy比random.choices
快一个数量级,而其他来自随机的选项似乎仍然较慢(more details here) :
my_list = random.choices('abc', k=1000)
# 276 µs ± 6.3 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
这意味着如果我为我的应用程序一次性生成并加入我的列表,这两种方法的速度大致相同。但它让我想知道为什么 numpy一旦我将联接操作带入混合中就无法保持领先。