【发布时间】:2015-04-27 20:14:14
【问题描述】:
替代标题:
使用比std::priority_queue 更快的方式 实现最小堆。
grpof 给了我:
时间秒秒呼叫s/呼叫s/呼叫名称
84.12 105.54 105.54 320000 0.00 0.00 _zn3rkdi24division_euclidean_spaceifee2nnejrkst6vectorifsaifeerkfrs3_ist4pairifiesaisb_eeriipjrst14priority_queueist5tupleijfiiees3_isj_saisj_eest7greaterisj_ees9_rkjs7_s7_i
我相信这是我在项目中使用的唯一std::priority_queue。 'Division_Euclidean_space' 部分让我感到困惑,因为它是我的项目中不再使用的类/文件。
这正是我使用的:
/**
* Min_heap is actually a std::priority_queue,
* with std::greater as a parameter.
*/
typedef std::priority_queue<std::tuple<float, int, int>,
std::vector<std::tuple<float, int, int> >,
std::greater<std::tuple<float, int, int> > > Min_heap;
我使用第一个元素作为比较的关键。
正如我在repo 中看到的那样,我只创建了一个Min_heap,并分两部分使用它:
if(...) {
branch.push(std::make_tuple(new_dist, other_child_i, tree_i));
}
和
while (branch.size()) {
std::tie(new_mindist, node_i, tree_i) = branch.top();
branch.pop();
...
}
我觉得如果我用别的东西替换这个数据结构,我的项目可能会运行得更快一些(超级棒)。有什么想法吗?
我将项目推送到堆中一段时间,然后我弹出一个,我可能会推送其他项目,依此类推。大多数时候我会在另一个条件下停止,而不是在堆变空时。
【问题讨论】:
-
那个 gprof 函数是
RKD<Division_Euclidean_space<float> >::nn,其中priority_queue只是参数之一。整个名字很长,你可以通过c++filt -n运行你的错位字符串来获得它。 -
我和其他人对 gprof 的看法很模糊,因为它告诉你一些愚蠢的东西,比如“库函数 xyz 是我的瓶颈”。休息一下,try this method。我的怀疑是,如果你只是用一个简单的链表替换所有这些花哨的东西,并且如果你在空闲列表中回收使用过的对象,你会看到一个数量级或更多的加速。
-
@MikeDunlavey 你的意思是用单个链表替换最小堆?我不确定您所说的回收和免费列表是什么意思。此外,我已经看到了链接,谢谢!题外话:顺便尊重飞行员/:)
-
我认为这值得提出一个新问题:stackoverflow.com/questions/29914485/…
-
“尊重飞行员”的评论超出了我的想象——抱歉。回收使用过的对象是一项基本技术,可以显着减少在新建和删除、构造函数和析构函数中花费的时间。如果您使用堆作为优先级队列,我怀疑它比简单链表更有效的交叉大小相当大。
标签: c++ performance stl gprof