web-dev-qa-db-ja.com

高性能のHaskellハッシュ構造。

私はalotのテーブル検索を行うプログラムを書いています。そのため、Data.Map(もちろん)だけでなくData.HashMapData.Hashtableにも出会ったとき、Haskellのドキュメントをよく読んでいました。私はハッシュアルゴリズムの専門家ではありません。パッケージを調べたところ、それらはすべて本当に似ているように見えます。そのように私は思っていました:

1:主な違いは何ですか?

2:〜4000のキーと値のペアのマップ/テーブルで大量のルックアップを行う場合、どちらが最もパフォーマンスが良いでしょうか?

49
providence

1:主な違いは何ですか?

  • Data.Map.Mapは内部的にバランスのとれたバイナリツリーであるため、ルックアップの時間の複雑さはO(log n)です。私はそれが " persistent "データ構造であると考えています。つまり、構造の関連する部分のみが更新された状態で変更操作が新しいコピーを生成するように実装されています。
  • Data.HashMap.MapData.IntMap.IntMap内部的に、パトリシアツリーとして実装されます。ルックアップの時間の複雑さはO(min(n、W))です。ここで[〜#〜] w [〜#〜]はビット数です整数で。また、「永続的」です。
  • Data.HashTable.HashTableは実際のハッシュテーブルで、時間の複雑さはO(1)ですが、ルックアップの場合です。ただし、変更可能なデータ構造です。操作はインプレースで行われるため、行き詰まっています。 IOモナドで使用したい場合。

2:〜4000のキーと値のペアのマップ/テーブルで大量のルックアップを行う場合、どちらが最もパフォーマンスが良いでしょうか?

残念ながら、私があなたに与えることができる最良の答えは「それは依存する」です。漸近的な複雑さを文字通りとると、O [log 4000)=約12がData.Map、O(min(4000、64))= 64 for Data.HashMapおよびO(1) = 1 for Data.HashTable。しかし、それは実際にはそのようには機能しません...コードのコンテキストでそれらを試す必要があります。

50
mergeconflict

_Data.Map_と_Data.HashMap_の明らかな違いは、前者はOrdにキーを必要とし、後者はHashableキーを必要とすることです。共通キーのほとんどは両方なので、それは決定的な基準ではありません。私は_Data.HashTable_についてまったく経験がないので、コメントすることはできません。

_Data.HashMap_と_Data.Map_のAPIは非常に似ていますが、_Data.Map_はより多くの関数をエクスポートします。alterなどの一部は_Data.HashMap_にありませんが、その他は厳格および非厳格のバリアント、_Data.HashMap_(私は nordered-containers からのハッシュマップを意味していると思います)は、別々のモジュールで遅延および厳格なAPIを提供します。 APIの共通部分のみを使用している場合、切り替えは本当に簡単です。

パフォーマンスに関しては、_Data.HashMap_ of nordered-containers の検索がかなり高速で、最後に測定しましたが、特に_Data.IntMap_または_Data.Map_よりも明らかに高速でした。 nordered-containers の(まだリリースされていない)HAMTブランチ。挿入については、多かれ少なかれ_Data.IntMap_と同等であり、_Data.Map_よりも多少高速でしたが、私は少しあいまいです。

どちらもほとんどのタスクに対して十分なパフォーマンスを発揮します。そうでないタスクについては、とにかくオーダーメイドのソリューションが必要になるでしょう。ルックアップについて具体的に尋ねることを考慮して、私は_Data.HashMap_にエッジを与えます。

11
Daniel Fischer

Data.HashTableのドキュメントに、「 hashtables パッケージを使用する」と記載されています。ハッシュテーブルが優れたパッケージである理由を説明する素敵なブログ投稿があります here 。 STモナドを使用します。

2
gatoatigrado