2012-04-17 5 views
2

unordered_setから「1つの要素を削除する」機能が必要です。erase(begin())を使用してunordered_setから1つの要素を削除するのがgccで遅い

ただし、消去(begin())を使用して実装すると非常に遅くなります。 (これはg ++ - 4.5.3です;多分begin()はより多くの空のハッシュバケットを横断しなければなりませんか?)

驚くべきタイミングで下のサンプルコードを見てください。

効率性の高い「1つの要素を削除」を実装する方法はありますか? (私はイテレータを無効になり、他の介在セット操作を許可したいん。)

#include <unordered_set> 
#include <iostream> 
#include <chrono> 
using namespace std; 

struct Timer { 
    Timer(string s) : _s(s), _start(Clock::now()) { } 
    ~Timer() { 
     auto t=chrono::duration_cast<chrono::milliseconds>(Clock::now()-_start).count(); 
     cerr << "Timer(" << _s << ") = " << t << "ms\n"; 
    } 
private: 
    typedef chrono::high_resolution_clock Clock; 
    string _s; 
    Clock::time_point _start; 
}; 

int main() 
{ 
    unordered_set<int> s; 
    const int num=200000; 
    { Timer t("insert"); for (int i=0;i<num;i++) { s.insert(i); } } 
    { Timer t("remove half"); for (int i=0;i<num/2;i++) { s.erase(s.begin()); } } 
    long long s1=0, s2=0; 
    { Timer t("access begin()"); for (int i=0;i<num/2;i++) { s1+=*s.begin(); } } 
    { Timer t("access all"); for (auto it=s.begin();it!=s.end();++it) { s2+=*it; } } 
    cerr << s1 << " " << s2 << "\n"; 
    return 0; 
} 

// Timer(insert) = 36ms 
// Timer(remove half) = 3039ms 
// Timer(access begin()) = 5958ms 
// Timer(access all) = 1ms 
+0

このテストでは、間に何もせずに、次々と多くの要素が削除されます。実際のプログラムの振る舞いとは異なるかもしれません。より大きな目標を記述してください。 unordered_set以外のものを使用する必要があるかもしれません。 – zwol

+0

1つの要素を削除したり、N個の要素をunordered_setから削除したりするのを最適化しますか? –

答えて

6

それは、より新しいバージョンで修正されたGNUライブラリ、そのバージョンでの問題のように見えます。ここに私のテストの結果は、私がインストールされているために起こる2つのバージョンを使用して、以下のとおりです。

[email protected]:~$ g++-4.4.5 -std=c++0x -O3 test.cpp 
[email protected]:~$ ./a.out 
Timer(insert) = 15ms 
Timer(remove half) = 3815ms 
Timer(access begin()) = 7722ms 
Timer(access all) = 0ms 
10000000000 14999950000 

[email protected]:~$ g++-4.6.1 -std=c++0x -O3 test.cpp 
[email protected]:~$ ./a.out 
Timer(insert) = 16ms 
Timer(remove half) = 2ms 
Timer(access begin()) = 0ms 
Timer(access all) = 1ms 
10000000000 14999950000 

私もboost::unordered_setを使用することにより、同様に高速な結果を得たので、それはあなたがあなたのコンパイラを更新できない場合はオプションです。

+0

ありがとうマイク。コンパイラの次のバージョンを楽しみにしています。 – Hugues

関連する問題