我正在比較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