C++:使用更大的比较器意外提升性能

C++: Unexpected performance boost using greater comparator

本文关键字:意外 比较器 性能 C++      更新时间:2023-10-16

我正在将算法问题的解决方案提交给在线评分系统,起初,解决方案超过了时间限制,大约需要~4s。

我完全确定复杂性是正确的,所以我开始优化我的部分代码,没有什么了不起的事情发生,直到我注意到一些非常奇怪的事情。

我正在使用对的优先级队列,我选择实现我自己的比较器

struct Comparator{  
bool operator()(pair<int, int> node1, pair<int, int> node2){  
return node1.second < node2.second;  
}  
}; 

当我将其更改为<algorithm>库的greater比较器时,性能得到了显着提升;解决方案通过了,只需要~300ms。

额外信息:我正在使用优先级队列来实现Dijkstra的"调整"版本。队列声明是:priority_queue<pair<int, int>, vector<pair<int, int>>, Comparator> q;,我将其更改为:priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> q;.

我真的很好奇为什么会发生这种情况。对我来说,比较器应该做什么非常简单,我想不出更有效的方法。

任何帮助将不胜感激:)

有几种情况可能导致性能差异:

struct Comparator{  
bool operator()(pair<int, int> node1, pair<int, int> node2){  
return node1.second < node2.second;  
}  
}; 

与。std::greater

  1. 自定义比较器按值获取对象,std::greater按引用获取对象。我怀疑这会产生超过 10% 的效果。
  2. std::greater比较node2.first < node1.first如果node2.first != node1.first否则它是node2.second < node1.second.这种比较与Comparator完全不同,后者比较node1.second < node2.second

    由于比较结果不同,因此代码将经历完全不同的路径。经历不同的路径会对大O的复杂性和性能产生深远的影响。这很可能是造成差异的真正原因。

有关std::greater参考,请查看std::pair::operator<正在做什么:

如果lhs.first<rhs.first,则返回true。否则,如果rhs.first<lhs.first,则返回false。否则,如果lhs.second<rhs.second,则返回true。否则,返回false