我正在比较STL(g ++)priority_queue的性能,发现push和pop没有我期望的那么快。见下面的代码:为什么在这种情况下,STL的priority_queue比multiset快不了多少?
#include <set>
#include <queue>
using namespace std;
typedef multiset<int> IntSet;
void testMap()
{
srand(0);
IntSet iSet;
for (size_t i = 0; i < 1000; ++i)
{
iSet.insert(rand());
}
for (size_t i = 0; i < 100000; ++i)
{
int v = *(iSet.begin());
iSet.erase(iSet.begin());
v = rand();
iSet.insert(v);
}
}
typedef priority_queue<int> IntQueue;
void testPriorityQueue()
{
srand(0);
IntQueue q;
for (size_t i = 0; i < 1000; ++i)
{
q.push(rand());
}
for (size_t i = 0; i < 100000; ++i)
{
int v = q.top();
q.pop();
v = rand();
q.push(v);
}
}
int main(int,char**)
{
testMap();
testPriorityQueue();
}
我编译这个-O3然后跑去的valgrind --tool = callgrind,KCachegrind testMap花费总CPU testPriorityQueue的54%需要CPU
的44%(无 - O3 testMap比testPriorityQueue) 似乎把大部分时间用于testPriorityQueue该功能被称为
void std::__adjust_heap<__gbe_cxx::__normal_iterator<int*, std::vector<int, std::allocator<int> > >, long, int, std::less<int> >
这个功能似乎从弹出称为快得多()打电话。
这个函数到底做了什么?有没有办法通过使用不同的容器或分配器来避免它?
是不是堆缓存不友好?至少这是我的一般印象。 – Mehrdad 2012-08-03 17:37:10
我认为他们以不可预知的方式分支了很多。该函数看起来像是什么负责堆“冒泡”,这是log(n)操作,每次删除元素以保持其顺序时,必须在堆上执行该操作。 – Wug 2012-08-03 17:46:21
CPU%不是测试性能或速度的有用方法。 '__adjust_heap'“重新平衡”优先级队列,并且是处理优先级队列时唯一缓慢的操作。这是先验队列的内在特征,我能想到的唯一选择是'std :: set',它必须以类似的方式进行平衡。 – 2012-08-03 17:50:33