【问题标题】:Is there something faster than a min heap for my use case?对于我的用例,有没有比最小堆更快的东西?
【发布时间】:2021-01-19 23:57:52
【问题描述】:

我的用例如下:

  1. 我需要获取一组生长元素中的最小值;我只需要任何迭代的最小值
  2. 我将更新最小值,之后保证不再是最小值,但它在订单中的新位置通常不能直接计算。
  3. 我将这个新值推回集合中,然后进入下一个迭代,在其中查看新的 min 元素。

现在我正在以下列方式使用 std::vector 和 std::pop_heap std::push_heap 。我在我的向量上调用 std::pop_heap ,它将最小元素推到向量的后面,我得到一个对最后一个元素的引用并更新它,然后我调用 std::push_heap 它将最后一个元素移动到它的新位置.所以我不必将结构从 std::vector 中复制出来来更新它。有问题的结构是 16 字节,可简单构造,它非常基本,完全由整数类型组成。

根据我的分析器和一系列问题大小,我看到的是,我在 std::pop_heap 中花费了超过 75% 的 cpu 时间,在 std::push_heap 中花费了 ~10%。现在,在每个被检查的最小元素上执行的逻辑非常简单,主要包括添加和与固定输入的一些比较,所以我认为这可能是最好的。但是,如果有一个不同的或随机的奇怪数据结构可能比我目前使用的 min_heap 更快,那么尝试一下会很有趣。

我已经尝试过 std::min_element、std::nth_element、std::sort ,对于 1,000,000 或更少的问题大小,我当前的解决时间不到 1 秒,并且运行时间增加了幅度(许多 10 秒)。考虑到它们的复杂性都比 std::push_heap 和 std::pop_heap 更糟糕,我会这样认为。

我也尝试过使用 std::map 和 std::set 等树结构,但这些也会降低性能(我现在手头没有数字)。

那么对于这个用例,有没有人知道比 min_heap 更好的东西?

(很遗憾我无法提供源代码,但考虑到 85% 的 cpu 时间都花在了 pop_heap/push_heap 上,我不认为它会超级有用)

编辑:比较运算符是两个整数类型之间的单个比较。所以它不像堆中使用的比较运算符正在做大量的工作。

【问题讨论】:

  • 当你更新最小值时,它的新位置通常是更靠近根还是更靠近堆的“末端”?
  • 你有没有试过不包含被删除元素但存储所有被删除元素的最小值并在最小值较小时再次插入的排序向量?
  • 您的代码每次迭代调用push_heap()pop_heap() 多少次?理想情况下,它只是每个迭代中的一个(当您将最小值从堆中弹出,更新它,然后将其推回),加上一个push_heap() 调用,用于您碰巧推入的每个新项目同时设置元素集。如果不止于此,请检查以确保您没有做一些低效的事情(例如在每次迭代时清除堆并从头开始重新填充它)
  • @harold 通常更接近最小值而不是最大值,但这对于任何给定的迭代都不能保证。
  • @henk 元素没有被删除它们被修改并推回,最小元素的值在算法的生命周期内缓慢增长

标签: c++ performance data-structures


【解决方案1】:

您可以就地更改值并从根开始向下冒泡,而不是删除最小元素并重新插入更新的值。删除最小元素通常会用最差的元素之一来替换根,通常会花费 long 下气泡,然后重新插入相对较小的值也会花费相对较长的上气泡.只要新值平均保持在相对接近根的位置,就地更改键将仅用一个向下气泡替换这两个键,这通常也更短。

遗憾的是,<algorithm> 中没有此功能,但您自己推出并不太难。把它写成 moves 通过制作根的临时副本留下的“洞”,而不是一系列std::swaps。使用 swaps 可以使加载和存储的总数增加一倍左右。

使用heap of larger arity(可能是 4 个,也可能是 8 个)可能会有所帮助。

【讨论】:

  • 就地更新和编写我自己的下推方法是我尚未尝试过的,所以我一定会研究一下,不确定在这种情况下增加 arity 会如何影响事情,但也值得一试看;谢谢!
  • 所以我检查了实现我自己的堆筛选算法并修改了 min 元素,这让我得到了 30-60%,具体取决于问题的大小。现在我的分析器指向单个比较运算符,所以我认为为了进一步改进,我需要存储更少的状态:)
猜你喜欢
  • 1970-01-01
  • 2020-10-02
  • 1970-01-01
  • 2010-10-05
  • 2012-04-15
  • 2015-07-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多