web-dev-qa-db-ja.com

超高性能C / C ++ハッシュマップ(テーブル、辞書)

高性能なハッシュマップデータ構造で値を構造化するには、プリミティブキー(int、多分長い)をマップする必要があります。

私のプログラムにはこれらのマップが数百個あり、各マップには通常数千個のエントリがあります。ただし、マップは常に「更新」または「攪拌」されます。数百万のaddおよびdeleteメッセージを1秒間処理することを想像してください。

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

77

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

30
Scharron

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

LGPL'd Judy array をチェックしてください。自分を使ったことはありませんが、いくつかの機会に宣伝されました。

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

また、最終的なソリューションのパフォーマンスがソリューションのコストを上回っている場合、十分なRAMでシステムを注文して、すべてをプレーンな配列に入れてください。インデックスによるアクセスのパフォーマンスは無敵です。

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

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

11
Dummy00001

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

11
Mark B

マルチスレッドプログラムを使用している場合、 intel thread building blocks library でいくつかの便利なハッシュテーブルを見つけることができます。たとえば、tbb :: concurrent_unordered_mapはstd :: unordered_mapと同じapiを持っていますが、その主な機能はスレッドセーフです。

また、facebookの folly library を見てください。高性能な hash tableskip list を同時に使用できます。

6
Pavel Davydov

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

3
zhanxw

from Android sources(したがって、Apache 2のライセンス)

https://github.com/CyanogenMod/Android_system_core/tree/ics/libcutils

hashmap.cを見て、include/cutils/hashmap.hを選択します。スレッドセーフが必要ない場合は、mutexコードを削除できます。サンプル実装はlibcutils/str_parms.cにあります。

3
sherpya

まず、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
computinglife

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

2
sjain

Miscellaneous Container Templates のハッシュテーブルを試してください。そのclosed_hash_mapは、Googleのdense_hash_mapですが、使いやすく(含まれる値に制限はありません)、他にもいくつかの特典があります。

2
doublep

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

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

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

これは基本的に、標準は実装がリンクリストに基づいている必要があることを示していることを意味します。これにより、パフォーマンスが向上するオープンアドレッシングが防止されます。

Googleのスパースはオープンアドレッシングを使用していると思いますが、これらのベンチマークでは競合製品よりも優れたバージョンのみが優れています。ただし、スパースバージョンは、メモリ使用量のすべての競合よりも優れています。 (また、プラトーはなく、要素の数に対して純粋な直線がありません)

1
v.oddou