【问题标题】:Why is random.shuffle so much slower than using sorted function?为什么 random.shuffle 比使用 sorted 函数慢得多?
【发布时间】:2021-03-10 17:19:49
【问题描述】:

当使用 pythons random.shuffle 函数时,我注意到使用 sorted(l, key=lambda _: random.random()) 比使用 random.shuffle(l) 快​​得多。据我了解,这两种方式都会产生完全随机的列表,那么为什么shuffle 需要这么长时间呢?

以下是使用timeit 模块的时间。

from timeit import timeit
setup = 'import random\nl = list(range(1000))'

# 5.542 seconds
print(timeit('random.shuffle(l)', setup=setup, number=10000))

# 1.878 seconds
print(timeit('sorted(l, key=lambda _: random.random())', setup=setup, number=10000))

【问题讨论】:

  • 理想情况下,shuffle 函数实现Fisher–Yates shuffle,它具有 O(n) 运行时复杂度,而一般排序具有 O(n log n) 运行时复杂度。我怀疑sorted(l, key=lambda _: random.random()) 不是洗牌数组的正确方法:请参阅提到的链接。
  • @user4642212:Python 是 Fisher-Yates(假设我正在正确阅读 Wikipedia 和 random.shuffle 源代码)。该链接确实提到 sortedrandom.random() 是正确的

标签: python performance random shuffle


【解决方案1】:

在 CPython(参考解释器)上,random.shuffle 是在 Python 中实现的(并根据 _randbelow 实现,它本身就是一个围绕 getrandbits 的 Python 包装器,它是最终实现它的 C 级函数,并且可以最终实现为了确保输出的公正性,被调用的频率几乎是严格必要的两倍); sorted(和 random.random)是用 C 实现的。用 Python 执行工作的开销高于用 C 执行类似工作。

【讨论】:

  • 如果 random.shuffle 使用 C 运行得更快,为什么不使用 sorted 返回列表?
  • @Evan:它使用了一种相当艰苦的算法来保证(在 PRNG 的范围内)完美的洗牌;避免偏见是一个令人惊讶的难题,与其确保它绝对正确,不如让它更快。 random 模块中存在许多错误,导致输出出现轻微偏差(这就是为什么 _randbelow 以现在的方式实现的原因),而且他们通常对使用更快的算法非常敏感t 可证明是公正的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-12-26
  • 2011-01-25
  • 2012-12-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多