Std :: mapは順序付けられたマップなので、値を挿入するたびに、マップはアルゴリズムを使用してアイテムを内部的にソートしますが、これには時間がかかります。
私のアプリケーションは、一定の間隔でいくつかのアイテムに関する情報を取得します。
このアプリは、次のように定義されたマップを保持しています。
::std::map<DWORD, myItem*>
最初は、すべてのアイテムが「新規」と見なされます。 「アイテム」オブジェクトが割り当てられ、このマップに追加されています。そのIDとポインターが関連付けられています。
「新しい」アイテムではない場合(このオブジェクトの更新のみ)、アプリは、指定されたIDを使用してマップでオブジェクトを検索し、更新する必要があります。
ほとんどの場合、更新を取得します。
私の質問は:
より高速なマップ実装はありますか、またはこれを引き続き使用する必要がありますか?
私はunordered_mapを使用した方がよいですか?
Unordered_mapを使用した方がよいですか?
たぶん。
std:map
は、バランスの取れたツリーとして実装する必要があるため、O(log n)で一貫したパフォーマンスを提供します。だが std:unordered_map
は、O(1)パフォーマンス(良いハッシュ関数とハッシュバケット間でのキーの分散)を提供する)が可能なハッシュテーブルとして実装されますが、O(n)(1つのハッシュバケット内のすべてのものとリストに展開されます)通常、これらの極端な中間の何かが予想されます。
したがって、常に妥当なパフォーマンス(O(log n))を得ることができます。またはyoは、ハッシュで良好なパフォーマンスを得るためにすべてが揃うようにする必要があります。
そのような質問と同様に、1つのアプローチに取り組む前に測定する必要があります。データセットが大きくない限り、大きな違いはないことに気付くでしょう。
重要な警告:マップのパフォーマンスがアプリケーションのパフォーマンスに実質的に影響することを測定していない限り(そして、質問でそうしていないことが示唆されている場合を除く)、マップの検索と更新に大きな時間を費やしています)それをより速くすることに悩む。 std::map
(またはstd::unordered_map
または利用可能なhash_map
実装)を使用してください。アプリケーションを1%高速化することは、おそらく努力する価値がありません。代わりに、バグのないようにしてください。
リチャードの答えをエコーする:measure実際のクラスと実際のデータを使用した、異なるマップ実装でのパフォーマンス。
追加のメモ:
予想コスト(ハッシュマップは通常それが低い)、最悪の場合のコスト(バランスの取れたバイナリツリーではO(logn)ですが、挿入がハッシュ配列の再割り当てをトリガーした場合のハッシュマップでははるかに高い)と償却コスト(合計コストを数値で割った値)の違いを理解します操作または要素の;新しい要素と既存の要素の比率のようなものに依存します)。あなたの場合、どちらがより制約的であるかを見つける必要があります。たとえば、非常に低いレイテンシ制限を守る必要がある場合、ハッシュマップの再割り当ては多すぎる可能性があります。
実際のボトルネックがどこにあるかを調べます。マップでの検索のコストは、たとえば、 IOコスト。
より特殊なマップ実装を試してください。たとえば、マップのキーについて何か知っていれば、多くのことが得られます。一般的なマップ実装の作成者は、そのような知識を持っていません。
あなたの例(強くクラスター化されている32ビットの符号なし整数キー、たとえば順次割り当てられている)では、基数ベースのアプローチを使用できます。 Very簡単な例(レシピとして使用する準備ができていないため、イラストとしてそれを脅かしてください):
Item *sentinel[65536]; // sentinel page, initialized to NULLs.
Item (*pages[65536])[65536]; // list of pages,
// initialized so every element points to sentinel
次に、検索は次のように簡単です。
Item *value = pages[index >> 16][index & 0xFFFF];
新しい値を設定する必要がある場合:
if (pages[index >> 16] == sentinel) {
pages[index >> 16] = allocate_new_null_filled_page();
}
pages[index >> 16][index & 0xFFFF] = value;
マップの実装を微調整します。
例えば。すべてのhash_map
は、事前におおよその要素数を知りたいと思っています。これは、ハッシュテーブルの不必要な再割り当てと(場合によっては)すべてのキーの再ハッシュを回避するのに役立ちます。
上記の特別な例では、確かに異なるページサイズ、または3レベルバージョンを試してみます。
一般的な最適化は、小さなオブジェクトの複数の割り当てを回避するために、特殊なメモリアロケータを提供することです。
アイテムを挿入または削除するたびに、メモリの割り当て/割り当て解除に多くのコストがかかります。代わりに、次のようなアロケーターを使用できます: https://github.com/moya-lang/Allocator std :: mapを2倍高速化著者は言うが、特に他のSTLコンテナの場合はさらに速くなることがわかりました。