简体   繁体   English

np.shuffle比np.random.choice慢得多

[英]np.shuffle much slower than np.random.choice

I have an array of shape (N, 3) and I'd like to randomly shuffle the rows. 我有一个形状数组(N,3),我想随机地随机排列行。 N is on the order of 100,000. N约为100,000。

I discovered that np.random.shuffle was bottlenecking my application. 我发现np.random.shuffle阻碍了我的应用程序。 I tried replacing the shuffle with a call to np.random.choice and experienced a 10x speed-up. 我尝试通过调用np.random.choice代替随机播放,并经历了10倍的加速。 What's going on here? 这里发生了什么? Why is it so much faster to call np.random.choice? 为什么调用np.random.choice这么快? Does the np.random.choice version generate a uniformly distributed shuffle? np.random.choice版本是否生成均匀分布的随机播放?

import timeit

task_choice = '''
N = 100000
x = np.zeros((N, 3))
inds = np.random.choice(N, N, replace=False)
x[np.arange(N), :] = x[inds, :]
'''

task_shuffle = '''
N = 100000
x = np.zeros((N, 3))
np.random.shuffle(x)
'''

task_permute = '''
N = 100000
x = np.zeros((N, 3))
x = np.random.permutation(x)
'''

setup = 'import numpy as np'

timeit.timeit(task_choice, setup=setup, number=10)
>>> 0.11108078400138766

timeit.timeit(task_shuffle, setup=setup, number=10)
>>> 1.0411593900062144

timeit.timeit(task_permute, setup=setup, number=10)
>>> 1.1140159380011028

Edit: For anyone curious, I decided to go with the following solution since it is readable and outperformed all other methods in my benchmarks: 编辑:对于任何好奇的人,我决定采用以下解决方案,因为它易于读取并且优于基准测试中的所有其他方法:

task_ind_permute = '''
N = 100000
x = np.zeros((N, 3))
inds = np.random.permutation(N)
x[np.arange(N), :] = x[inds, :]
'''

You're comparing very different sized arrays here. 你在这里比较非常不同大小的数组。 In your first example, although you create an array of zeros, you simply use random.choice(100000, 100000) , which pulls 100000 random values between 1-100000. 在第一个示例中,尽管您创建了一个零数组,但您仅使用random.choice(100000, 100000) ,即可在1-100000之间提取100000个随机值。 In your second example your are shuffling a (100000, 3) shape array. 在第二个示例中,您将改组(100000, 3)形状数组。

>>> x.shape
(100000, 3)
>>> np.random.choice(N, N, replace=False).shape
(100000,)

Timings on more equivalent samples: 更多等效样本的时间:

In [979]: %timeit np.random.choice(N, N, replace=False)
2.6 ms ± 201 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

In [980]: x = np.arange(100000)

In [981]: %timeit np.random.shuffle(x)
2.29 ms ± 67.3 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

In [982]: x.shape == np.random.choice(N, N, replace=False).shape
Out[982]: True

permutation and shuffle are linked, in fact permutation calls shuffle under the hood!! permutationshuffle是链接在一起的,实际上permutationpermutation称为shuffle !!

The reason why shuffle is slower than permutation for multidimensional array is that permutation only need to shuffle the index along the first axis. shuffle比多维数组的permutation慢的原因是, permutation仅需要沿第一个轴shuffle permutation索引。 Thus becomes a special case of shuffle of 1d array (the 1st if-else block). 因此成为1d数组(第一个if-else块)的shuffle的特例。

This special case is also explained in the source as well: 源代码中也解释了这种特殊情况:

# We trick gcc into providing a specialized implementation for
# the most common case, yielding a ~33% performance improvement.
# Note that apparently, only one branch can ever be specialized.

For shuffle on the otherhand, multidimensional ndarray operation requires a bounce buffer, creating that buffer, especially when the dimension is relative big, becomes expensive. 另一方面,对于shuffle ,多维ndarray操作需要反弹缓冲区,因此创建缓冲区特别是在维数相对较大时尤其昂贵。 Additionally, we can no longer use the trick mentioned above that helps the 1d case. 此外,我们将无法再使用上述有助于1d情况的技巧。

With replace=False and using choice to generate a new array of the same size, choice and permutation is the same, see here . 使用replace=False并使用choice生成相同大小的新数组时, choicepermutation相同,请参见此处 The extra time would have to come from the time spend in creating intermediate index arrays. 多余的时间必须来自创建中间索引数组所花费的时间。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM