超高性能C / C ++ハッシュマップ(表、辞書)[クローズ]


84

高性能ハッシュマップデータ構造で値を構造化するには、プリミティブキー(int、おそらくlong)をマップする必要があります。

私のプログラムにはこれらのマップが数百あり、各マップには通常最大で数千のエントリがあります。ただし、マップは常に「更新」または「チャーン」されます。何百万もの処理を想像addし、delete第二のメッセージ。

CまたはC ++のどのライブラリが、このユースケースに適合するデータ構造を持っていますか?または、独自に構築することをどのように推奨しますか?ありがとう!


1
キーによる検索をデータに処理する必要がありますか?
ギヨームルブルジョワ2010

3
更新または取得はより頻繁になりますか?(追加/削除、またはキーを変更しない読み取り/更新)
falstro 2010

stackoverflow.com/questions/266206/…。これはおそらく始めるのに良い場所です。
DumbCoder 2010

2
@roe:追加/削除操作は、取得操作よりもはるかに(100倍)頻繁です。
Haywood Jablomey 2010

1
4年半後、何があなたのニーズに最もよく合っているかを知ることは興味深いでしょう。現在の回答のどれも満足のいくものではなかった場合は、自分で書いてそれを受け入れることができます。
Walter Tross 2015

回答:


31

Google SparseHash(またはC11バージョンのGoogle SparseHash-c11)を試して、ニーズに合っているかどうかを確認することをお勧めします。これらには、メモリ効率の高い実装と、速度が最適化された実装があります。私はずっと前にベンチマークを行いましたが、それは速度の点で利用可能な最高のハッシュテーブル実装でした(ただし欠点はあります)。


16
欠点について詳しく教えてください。
Haywood Jablomey 2010

IIRC、それはメモリの問題でした。要素を削除すると、要素は破壊されましたが、そのメモリはまだ生きていました(私が推測するキャッシュとして使用されました)。
Scharron 2010

4
@Haywood Jablomey:主な欠点は、1つまたは2つの(要素を消去した場合)値を分割し、それらを使用しないようにする必要があることです。場合によっては、これは簡単に実行できます。たとえば、負の整数などですが、そうでない場合もあります。
2010

3
今日、この推奨事項を支持しますか?
einpoklum 2018

11

CまたはC ++のどのライブラリが、このユースケースに適合するデータ構造を持っていますか?または、独自に構築することをどのように推奨しますか?ありがとう!

LGPLのJudyアレイをチェックしてください。自分自身を使用したことはありませんが、いくつかの機会に私に宣伝されました。

STLコンテナ(std :: hash_mapなど)のベンチマークを試すこともできます。プラットフォーム/実装およびソースコードの調整(動的メモリ管理にはできるだけ多くの費用がかかる)によっては、十分なパフォーマンスが得られる可能性があります。

また、最終的なソリューションのパフォーマンスがソリューションのコストよりも優れている場合は、すべてをプレーンアレイに配置するのに十分なRAMを備えたシステムを注文することができます。インデックスによるアクセスのパフォーマンスは無敵です。

追加/削除操作は、取得操作よりもはるかに(100倍)頻繁です。

これは、最初にアルゴリズムの改善に集中することをお勧めします。データが書き込まれるだけで、読み取られない場合、なぜそれらをまったく書き込むのですか?


11

デフォルトではboost::unordered_map(またはtr1など)を使用するだけです。次に、コードのプロファイルを作成し、そのコードがボトルネックであるかどうかを確認します。その場合にのみ、要件を正確に分析して、より迅速な代替品を見つけることをお勧めします。


15
です。VS2013std::unordered_mapは、処理の比較的小さな部分にのみマップを使用していますが、実行時間全体の90%以上を占めています。
キャメロン

6

マルチスレッドプログラムを使用している場合は、Intelスレッドビルディングブロックライブラリにいくつかの便利なハッシュテーブルがあります。たとえば、tbb :: concurrent_unordered_mapのAPIはstd :: unordered_mapと同じですが、主な機能はスレッドセーフです。

Facebookの愚かなライブラリも見てください。高性能の同時ハッシュテーブルスキップリストがあります。


4

ハッシは非常に効率的です。著者の詳細なベンチマークがあります:https://attractivechaos.wordpress.com/2008/10/07/another-look-at-my-old-benchmark/そしてそれはまたkhashが他の多くのハッシュライブラリを打ち負かすことを示しています。



2

まず、libmemcacheなどの既存のソリューションがニーズに合っているかどうかを確認します。

そうでない場合...

ハッシュマップはあなたの要件に対する明確な答えのようです。キーに基づいてo(1)ルックアップを提供します。最近のほとんどのSTLライブラリは、ある種のハッシュを提供しています。したがって、プラットフォームが提供するものを使用してください。

その部分が完了したら、ソリューションをテストして、デフォルトのハッシュアルゴリズムがニーズに対して十分なパフォーマンスを発揮するかどうかを確認する必要があります。

そうでない場合は、ネット上にあるいくつかの優れた高速ハッシュアルゴリズムを調べる必要があります

  1. 古き良き素数乗算アルゴ
  2. http://www.azillionmonkeys.com/qed/hash.html
  3. http://burtleburtle.net/bob/
  4. http://code.google.com/p/google-sparsehash/

これが十分でない場合は、自分でハッシュモジュールをロールすることができます。これにより、テストしたSTLコンテナーで発生した問題と、上記のハッシュアルゴリズムの1つが修正されます。結果は必ずどこかに投稿してください。

ああ、複数のマップがあるのは興味深いことです...おそらく、キーを64ビットnumとして使用し、上位ビットを使用して、それが属するマップを区別し、すべてのキーと値のペアを1つの巨大なハッシュに追加することで簡略化できます。基本的な素数ハッシュアルゴリズムで10万個程度のシンボルが完全に機能するハッシュを見てきました。

そのソリューションが何百ものマップと比較してどのように機能するかを確認できます..メモリプロファイリングの観点からはより良いと思います...この演習を行うことができたら、結果をどこかに投稿してください

ハッシュアルゴリズムよりも、メモリの継続的な追加/削除(回避できるか?)と、アプリケーションのパフォーマンスにとってより重要なCPUキャッシュ使用プロファイルである可能性があると思います。

幸運を



2

uthashをお勧めします。構造にを含めて#include "uthash.h"から追加UT_hash_handleし、構造内の1つ以上のフィールドを選択してキーとして機能させるだけです。ここでパフォーマンスについて一言。


1

http://incise.org/hash-table-benchmarks.htmlgccの実装は非常に優れています。ただし、非常に悪い標準的な決定を尊重する必要があることに注意してください。

再ハッシュが発生すると、すべてのイテレータは無効になりますが、個々の要素への参照とポインタは引き続き有効です。実際の再ハッシュが発生しない場合、変更はありません。

http://www.cplusplus.com/reference/unordered_map/unordered_map/rehash/

これは基本的に、標準では実装はリンクリストに基づいている必要があると述べていることを意味します。パフォーマンスが向上するオープンアドレス法を防ぎます。

グーグルスパースはオープンアドレッシングを使用していると思いますが、これらのベンチマークでは、高密度バージョンのみが競合他社を上回っています。ただし、スパースバージョンは、メモリ使用量のすべての競合を上回ります。(また、プラトーがなく、要素の数が純粋な直線です)


1
参照してください。これをバケットインターフェースも連鎖する必要がどのように説明しています。参照についてのポイントはとても良いです。有用な保証であると主張して言いたくなりますが、多くの場合、参照で要素を再度検索しないようにするだけです。通常の理由は、検索が遅すぎるためです...そうでない場合はそうではありません。参照を有効に保つ必要があるため、オープンアドレス法を使用できます。だから、それは少し鶏と卵のようです。これは2003年の提案を引用しており、その選択について明確に議論しています。
underscore_d
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.