8

std::unordered_setにポインタを格納しています。これを行うのは、重複が必要ないためです(コレクション内のポインターを削除するため、重複がある場合は、既に削除されているポインターを削除しようとします)。私はこれらのセットを頻繁にループします。std::vectorがループ(連続メモリ)の最速のコンテナであることを知っているので、std::unordered_setが同じことをするかどうか疑問に思いました。

そうでない場合は、std :: vectorを使用して、ポインターが既に削除されているかどうかを確認する方が速いでしょうか。

4

4 に答える 4

19

std::unordered_set隣接していますか?

コンテナの正確な実装は、標準では詳しく説明されていません...ただし、標準では、実際の表現を制約するいくつかの動作が規定されています。

たとえば、メモリに対して安定している必要があります。要素の参照/アドレスは、他のstd::unordered_set要素を追加/削除する場合でも有効です。

これを実現する唯一の方法は、要素を多かれ少なかれ独立して割り当てることです。連続したメモリ割り当てでは達成できません。そのような割り当ては必然的に制限されるため、要素をより大きなチャンクに再割り当てする可能性がなく、大きくなりすぎる可能性があります。

于 2013-01-17T18:05:23.813 に答える
4

いいえ、連続したメモリではありませんが、ハッシュマップのおかげで、それでも非常に高速です。

編集:ランダムアクセスが高速です。主にループを実行する場合は、別のコンテナーを検討する必要があると思います。

Edit2:そして、別のコンテナーについて考える価値があるかどうかを知るために、プロファイルを作成する必要があります。(多分あなたはどこか他の場所で最適化するべきです...多分)。

于 2013-01-17T17:27:32.063 に答える
4

次のメンバー関数がによって提供されているという事実はstd::unordered_map、それがハッシュテーブルに基づいていることを示唆しています。おそらく 、リンクリストを使用した個別のチェーンです。

bucket_count, hash_function, load_factor, max_load_count, rehash

要素が隣接しているかどうかは、アロケータによって異なります。およびのデフォルトのアロケータは、連続するメモリに要素を割り当てません。unordered_maplist各要素のメモリは、挿入時に割り当てられます。

ただし、事前に割り当てられたメモリプールから要素を割り当てることができるカスタムアロケータ(プールアロケータなど)を提供できます。それでも、データ構造内の論理的に隣接する要素は、メモリ内で物理的に隣接していない可能性があります。

したがって、すべての要素をループすることが最も頻繁な操作であるunordered_map場合、は最善の解決策ではない可能性があります。競合するすべてのソリューションのプロファイラーを介して主要なユースケースを実行すると、最良のソリューションが明らかになります。

それに加えて、unordered_map別の理由でループするのは最良の選択ではありません。名前に「 unordered 」という単語が含まれていることに注意してください。これは、、、、またはとは異なりlist、要素の順序がないことを示していvectorます。たとえば、メンバー関数は要素の相対的な順序を変更する場合があります。実際、 再ハッシュは、操作中に負荷率が超過するたびに、コンテナーによって自動的に実行されます。maprehashmax_load_factor

于 2013-01-17T18:35:24.543 に答える
1

std :: unordered_setはハッシュマップコンテナであると想定されているため、std::vectorと比較するとパフォーマンスが少し低下すると想定できます。

ただし、unordered_setアクセスが実際のホットスポットである場合は、実際のプロファイリング結果を確認する必要があると思います。

使用しているSTL実装が妥当なものである場合は、ポインターまたはint型キーの特殊化のようなベクトルを提供する必要があります。trueの場合、ポインタ型に特化したunordered_setは、自動的に拡大/縮小するベクトルのように動作し、パフォーマンスの違いは目立たなくなります。

于 2013-01-17T17:50:42.507 に答える