【问题标题】:Numpy's partition slower than sort for small arraysNumpy 分区比小数组的排序慢
【发布时间】:2017-09-21 04:07:14
【问题描述】:

我正在寻找一种有效的方法来计算 numpy 数组中的第 n 个最大值,this answer 将我引导至np.partition

顺便说一句,我注意到对于少于 100 个条目的数组,朴素排序比 np.partition 方法更快。 (相反,对于大型数组,增益是显而易见的)

小数组的 np.partition 运行时间几乎持平的原因是什么?

生成图片的代码:

import pandas as pd
import numpy as np

import timeit

def func_1(inp):
    return np.partition(inp, 10)[10]

def func_2(inp):
    return np.sort(inp)[10]

a = []
b = []

N_tests = int(1e5)

for wdw in range(20, 1000, 10):

    print wdw

    res1 = timeit.timeit("func_1(test)",
                      setup = "import pandas as pd; import numpy as np; wdw_size = %d; test = np.random.randn(wdw_size); from __main__ import func_1"%wdw, number = N_tests)

    a.append(res1)

    res2 = timeit.timeit("func_2(test)",
                      setup = "import pandas as pd; import numpy as np; wdw_size = %d; test = np.random.randn(wdw_size); from __main__ import func_2"%wdw, number = N_tests)

    b.append(res2)

import matplotlib.pyplot as plt
plt.plot(range(20,1000, 10), a, range(20, 1000, 10), b)
plt.legend(['np.partition', 'np.sort'])
plt.xlabel('Array Size')
plt.ylabel('Time')

【问题讨论】:

  • 对于可靠的基准,也许对较小的数据集使用更多的迭代?
  • 公平的建议。我已将迭代次数增加到 1e5,但仍获得相同的定性结果。
  • 答案可能很简单,“因为设置分区的开销更大”,即使原则上不应该这样。或许看看源代码?
  • 如果就地排序,时间比较如何?
  • func_1 和 func_2 都不使用 wdw 参数...

标签: python arrays performance sorting numpy


【解决方案1】:

根据文档,np.partition 是通过 Introselect 实现的 - 一种最坏情况下性能为 O(n) 的算法。

一句话,Introselect 是快速排序的增强版,在median of medians 的帮助下。

另一方面,np.sort 是使用普通的旧 快速排序 实现的,其最坏情况下的性能为 O(n^2)。 p>

所以比较两者,而np.sort 仅使用快速排序并且可能以 O(n^2) 作为其最坏情况的性能,np.partition 可以通过以下方式避免这种情况必要时退回中位数的中位数以始终确保 O(n)


不完全确定,但np.sort 可能对小型数组更快,因为np.partition 的算法更复杂,开销更大。

【讨论】:

  • 图表支持开销的想法。并且 O(n) 增加。
猜你喜欢
  • 2022-01-16
  • 2020-02-21
  • 2016-09-08
  • 2019-10-08
  • 1970-01-01
  • 2014-03-13
  • 1970-01-01
  • 2019-12-14
  • 2017-10-31
相关资源
最近更新 更多