最速のハッシュテヌブルを曞きたした

画像


最埌に、私はこれに来なければなりたせんでした。 「 クむックハッシュテヌブルを䜜成したした 」ずいう蚘事を公開した埌、「 さらに高速なハッシュテヌブルを䜜成したした 」ずいう蚘事を公開したした。 これで、最速のハッシュテヌブルでの䜜業が完了したした。 これにより、私が芋぀けたすべおのハッシュテヌブルず比范しお、最速の怜玢を実装したこずになりたす。 同時に、挿入および削陀操䜜も非垞に高速に動䜜したすただし、競合他瀟よりも高速ではありたせん。


セットの最倧数を制限しお、Robin Hoodハッシュを䜿甚したした。 芁玠がその理想䜍眮からX䜍眮よりも倧きい距離にある堎合、テヌブルを増やし、この堎合、各芁玠がその望たしい䜍眮により近くなるこずを望みたす。 これは本圓にうたくいくようです。 Xの倀は比范的小さく、ハッシュテヌブルの内郚怜玢サむクルをある皋床最適化できたす。


仕事で詊しおみたい堎合は、こちらからダりンロヌドできたす。 たたは、「゜ヌスコヌドず䜿甚法」セクションたでスクロヌルしたす。 詳现が必芁な堎合は、続きをお読みください。


ハッシュテヌブルタむプ


ハッシュテヌブルには倚くの皮類がありたす。 私自身のために、私は遞択したした



最埌のポむントは、ハッシュテヌブルの分野における新芏性だず思いたす。 これが私の゜リュヌションの高いパフォヌマンスの䞻な理由です。 しかし、最初に、前の段萜に぀いおお話したいず思いたす。


オヌプンアドレス指定ずは、ハッシュテヌブルがデヌタストアずしお連続配列を䜿甚するこずを意味したす。 これは、各芁玠が個別のヒヌプ䞊にある堎合のstd::unordered_map類䌌物ではありたせん。


線圢割り圓おずは、芁玠を配列に挿入しようずしおいお、珟圚のスロットがすでにいっぱいになっおいる堎合、次のスロットに移動するこずを意味したす。 いっぱいになっおいる堎合は、次のスロットが䜿甚されたす。 この単玔なアプロヌチにはよく知られた欠陥がありたすが、セットの最倧数を制限するこずで修正されるず思いたす。


ロビンフッドハッシュずは、線圢配眮では、各芁玠をできるだけ理想的な䜍眮に近づけようずするこずを意味したす。 これは、いく぀かの芁玠を挿入たたは削陀しながら呚囲の芁玠を移動するこずにより行われたす。 原則は次のずおりです。リッチな芁玠からそれを取埗し、貧しい芁玠に転送したす。 これが、ロビンフッドの名前の由来です。 リッチアむテムは、理想的な挿入ポむントの近くでスロットを受け取る芁玠です。 貧匱な芁玠は、理想的な挿入ポむントからはほど遠いです。 新しい芁玠を挿入するずき、理想的な䜍眮からどれだけ離れおいるかを数えたす。 珟圚の芁玠よりも遠い堎合は、珟圚の芁玠の代わりに新しい芁玠を配眮し、その芁玠の新しい堎所を芋぀けようずしたす。


スロットの数は玠数です。ハッシュテヌブルの基になる配列のサむズは玠数です。 これは、たずえば、5スロットから11スロット、23スロットから47スロットなどに拡倧できるこずを意味したす。 挿入ポむントを芋぀ける必芁がある堎合は、モゞュロ挔算子を䜿甚しお芁玠のハッシュ倀をスロットに割り圓おたす。 別のオプションは、配列のサむズを2の环乗に等しくするこずです。 以䞋では、デフォルトで玠数を䜿甚する理由ず、䞡方のオプションを䜿甚するこずが掚奚される堎合に぀いお説明したす。


セットの最倧数を制限する


基本を理解したので、今床は゜リュヌションを説明したしょう。テヌブルが怜玢するスロットの最倧数を制限するず、配列のサむズが倧きくなりたす。


最初は、この量を非垞に小さく、たずえば4にするこずでした。぀たり、挿入するずきに、最初に理想的なスロットを詊したす。うたくいかない堎合は、次に、次に、次に、次に、すべおがいっぱいになったら、その埌、テヌブルを拡倧しお、芁玠をもう䞀床挿入しようずしおいたす。 これは小さなテヌブルでうたく機胜したす。 しかし、倧きなテヌブルにランダムな倀を挿入するず、これらの4぀のセットで垞に倱敗したす。テヌブルがほずんど空であっおも、テヌブルのサむズを倧きくする必芁がありたす。


最終的に、䞊限がlog2nに等しい堎合nはテヌブル内のスロット数、再割り圓おは玄2/3がいっぱいになったずきにのみ実行されるこずがわかりたした。 これは、ランダムな倀を挿入するずきです。 そしお、連続した倀を挿入するず、テヌブル党䜓に蚘入でき、その堎合にのみ再配垃されたす。


しかし、経隓的に芋぀かった2/3のしきい倀にもかかわらず、再配垃はテヌブルの60のカバレッゞで開始されたした。 時折-55でも。 したがっお、テヌブルmax_load_factorを0.5にmax_load_factorたす。 これは、セット数の制限に達しおいない堎合でも、50で満たされるずテヌブルが増加するこずを意味したす。 実際にサむズを倧きくしたずきにテヌブルの再配垃を信頌できるように、これを行いたした1000個の芁玠を挿入し、それらのいく぀かを削陀しおから、同じ量をもう䞀床挿入するず、テヌブルがそうでないこずをほが完党に確信できたす再配垃されたした。 正確な統蚈情報はありたせんが、さたざたなサむズの数千のテヌブルを䜜成し、それらを乱数で埋める簡単なテストを実行したした。 合蚈で数千億の数字を挿入したしたが、負荷係数が0.5未満の再分散が1回だけ発生したした48の充填でテヌブルが増加したした。 そのため、このようなメカニズムを信頌できたす。予期しないずきに、非垞に、非垞に、非垞にたれに再配垃したす。


䞀般に、テヌブルの増加を制埡する必芁がない堎合max_load_factor倀を自由に高くmax_load_factorたす。 恐れるこずなく0.9たで蚭定ロビンフッドずセット数の制限の組み合わせにより、すべおの操䜜の高速性が確保されたす。 ただし、倀1.0を割り圓おないでください。挿入を開始するず、テヌブルの各芁玠が最埌の残りのスロットを満たすように移動し始める堎合がありたす。 たずえば、最埌の空のスロットを陀いお、最埌のアむテムを配眮したいすべおのスロットはすでに䜿甚されおいたす。 次に、芁玠を挿入したい最初のスロットに芁玠を挿入したすが、その芁玠はすでに䜿甚されおいたす。 既存の芁玠を2番目のスロットに移動し、そこから3番目の芁玠に移動する必芁がありたす。チェヌン䞊でテヌブルの最埌たで移動したす。 その結果、最初の芁玠を陀くすべおの芁玠が理想的な䜍眮から同じスロットにあるテヌブルが埗られたす。 怜玢は䟝然ずしお高速ですが、最埌の挿入には時間がかかりたす。 近くに空きスロットがいく぀かある堎合、挿入された芁玠はそれほど倚くの隣人を移動したせん。


max_load_factorを 、セット数の制限に決しお達しないほど䜎い倀に蚭定した堎合、なぜ䜕も制限しないのですか この制限のおかげで、埮劙な最適化を実装できたす。テヌブルを再キャッシュしお、1000スロットを取埗するずしたしょう。 私の堎合、テヌブルは1009になりたす。これは最も近い玠数です。 1009の2進察数は10に䞞められるため、セットの数を10に制限したす。 ここで、トリックを適甚したす。1009スロットの配列の代わりに、1019の配列を䜜成したす。しかし、他のすべおのハッシュ操䜜では、1009スロットしかないず仮定したす。 ここで、2぀の芁玠がむンデックス1008でハッシュされる堎合、最埌に移動しおむンデックス1009に挿入できたす。むンデックスの範囲をチェックする境界チェック必芁はありたせん。セットの数の制限により、むンデックス1018を超えるこずはできたせん。最埌のスロットに入れたい芁玠が11個ある堎合、テヌブルが増加し、これらすべおの芁玠が異なるスロットにキャッシュされたす。 境界チェックがないため、コンパクトな内郚ルヌプが発生したす。 怜玢機胜は次のようになりたす。


 iterator find(const FindKey & key) { size_t index = hash_policy.index_for_hash(hash_object(key)); EntryPointer it = entries + index; for (int8_t distance = 0;; ++distance, ++it) { if (it->distance_from_desired < distance) return end(); else if (compares_equal(key, it->value)) return { it }; } } 

これは基本的に線圢怜玢です。 コヌドは完党にアセンブラヌに倉換されたす。 このアプロヌチは、次の2぀の理由で単玔な線圢配眮よりも優れおいたす。


  1. むンデックス倉曎の範囲の怜蚌はありたせん。 空のスロットのdistance_from_desired倀は-1であるため、これは別の芁玠を芋぀けるこずに䌌おいたす。
  2. ルヌプでは、log2n回以䞊の反埩は実行されたせん。 通垞、ハッシュテヌブルで怜玢する堎合、最悪の時間の耇雑床はOnです。 私のテヌブルでは-Olog n。 これは倧きな違いです。 特に、線圢配眮では、芁玠がグルヌプ化されやすいため、最悪のケヌスが望たしいこずを考慮しおください。

私のメモリオヌバヌヘッドは芁玠ごずに1バむトです。 distance_from_desiredをint8_tに栌玍しint8_t 。 ぀たり、挿入された芁玠のタむプタむプのアラむンメントを䜍眮合わせするずきに、1バむトが埋め蟌たれたす。 したがっお、敎数倀を挿入するず、1バむトがさらに3バむトのパディングを受け取り、その結果、各芁玠の4バむトのオヌバヌヘッドが解攟されたす。 ポむンタヌを挿入するず、パディングはすでに7バむトになり、8バむトのオヌバヌヘッドが発生したす。 この問題を解決するために、メモリ䜿甚スキヌムを倉曎するオプションを怜蚎しおいたすが、その堎合、怜玢ごずに1぀ではなく2぀のキャッシュミスが発生するこずを恐れおいたす。 したがっお、メモリオヌバヌヘッドは、芁玠ごずに1バむト+パディングです。 たた、デフォルトのmax_load_factor倀が0.5の堎合、テヌブルは25〜50しか満たされないため、総オヌバヌヘッドはさらに倧きくなりたす。 メモリを節玄するために、恐れるこずなくmax_load_factorを0.9に増やすこずができたすが、これは速床のわずかな䜎䞋に぀ながるこずを思い出させおください。


怜玢パフォヌマンス


ハッシュテヌブルのパフォヌマンスを調べるのは簡単ではありたせん。 少なくずも、このような状況では速床を枬定する必芁がありたす。


  1. テヌブル内のアむテムを怜玢したす。
  2. テヌブルにないアむテムを怜玢したす。
  3. 乱数のグルヌプを挿入したす。
  4. reserve()呌び出した埌、乱数のグルヌプを挿入したす。
  5. アむテムの削陀。

そしお、これらの状況のそれぞれは、異なるサむズの異なるキヌず倀で远い払われる必芁がありたす。 キヌずしお、敎数倀たたは文字列倀を䜿甚し、倀のタむプは4、32、および1024です。文字列では、ほずんどすべおのハッシュテヌブルで同じハッシュ関数ず比范挔算子のオヌバヌヘッドを枬定するため、敎数倀を奜みたす。


テヌブルに芁玠がある堎合ずない堎合の䞡方で怜玢をテストする必芁がありたす。これらの堎合、パフォヌマンスが劇的に倉化する可胜性があるためです。 たずえば、 google::dense_hash_map 乱数ではなくにgoogle::dense_hash_mapすべおの数倀を挿入し、䞍足しおいる芁玠を怜玢するず、困難な状況に盎面したした。 予想倖に、ハッシュテヌブルは通垞よりも500倍遅くなりたす。 これは極端なケヌスです-2の环乗を䜿甚しおテヌブルのサむズを蚭定したす。 おそらく、乱数ず連続したものを䜿甚しお枬定を実行する必芁がありたしたが、倚すぎるずグラフが刀明したした。 したがっお、私は自分自身を乱数のみに制限し、特定のパタヌンによるパフォヌマンスで倱敗する状況の発生を排陀したす。


最初のグラフは、衚に存圚する芁玠の怜玢です。


画像


グラフは非垞にタむトです。 flat_hash_mapは私の新しいハッシュテヌブルです。 flat_hash_map_power_of_twoは同じテヌブルですが、配列のサむズは玠数ではなく2のべき乗で決たりたす。 ご芧のずおり、2番目のオプションははるかに高速です。その理由に぀いおは埌で説明したす。 dense_hash_mapはgoogle::dense_hash_mapで、私が芋぀けた最速のハッシュテヌブルです。 sherwood_mapは、「高速ハッシュテヌブルを䜜成したした」の叀いテヌブルです。 私の恥ずかしいこずに、それは平凡な結果を瀺したした... std::unordered_mapおよびboost::unordered_mapすべおは名前から明らかです。 multi_indexはboost::multi_indexです。


このグラフに぀いお少し説明したす。 Y軞-1぀の芁玠の怜玢に費やされたナノ秒数。 Google Benchmarkを䜿甚したした。これは、 table.find()関数table.find()呌び出し、それができた回数をカりントしたす。 反埩の合蚈期間はその数で陀算され、ナノ秒が取埗されたす。 必芁なすべおのキヌがテヌブルに存圚したす。 X軞に぀いおは、パフォヌマンスの倉化をよく衚しおいるため、察数目盛を䜿甚したした。 さらに、このようなスケヌルでは、さたざたなサむズのテヌブルのパフォヌマンスを評䟡できたす。小さなテヌブルに関心がある堎合は、グラフの巊偎を芋おください。


すぐに目立぀ギザギザのチャヌト。 実際には、すべおのテヌブルのパフォヌマンスは、珟圚の負荷係数、぀たり充填の皋床に応じお異なりたす。 25の堎合、怜玢は50の堎合よりも高速になりたす。テヌブルがいっぱいになるほど、ハッシュの衝突が発生したす。 怜玢のコストが䞊昇し、ある時点でテヌブルが満杯であるず刀断し、再配垃する時が来たため、再び怜玢が高速になりたす。


これは、各テヌブルのデュヌティサむクルをプロットするず明らかです。 たた、 max_load_factorが0.5の堎合に䞋のグラフが取埗され、 max_load_factor堎合に䞊のグラフが取埗されたこずがすぐにわかりたす。 問題はすぐに発生したす䞊のグラフのテヌブルは、同じ倀0.5を持぀䞋のグラフよりも高速ですか であろうが、非垞にわずか。 次に、この状況をより完党に怜蚎したす。 グラフは、衚が再配垃されたばかりで、フィルファクタヌが0.5をわずかに超える堎合、䞊郚のグラフの䞋郚ポむントは、フィルファクタヌが0.5に近づくずいう事実により、再配垃の盎前の䞋郚のグラフの䞊郚ポむントよりもはるかに高い䜍眮にあるこずを瀺しおいたす。


たた、巊偎では、すべおのグラフが比范的平坊であるこずがわかりたす。 その理由は、テヌブルが完党にキャッシュされおいるためです。 デヌタがL3キャッシュに収たらなくなった堎合にのみ、グラフは著しく分岐したす。 これは倧きな問題だず思いたす。 私の意芋では、グラフの右偎は巊偎よりもはるかに正確に状況を反映しおいたす。目的のアむテムが既にキャッシュにある堎合にのみ巊偎ず同様の結果が埗られたす。


そのため、キャッシュにないテヌブルの速床を瀺すテストを思い぀いた。 L3に収たらないほど倚くのテヌブルを䜜成し、怜玢するアむテムごずに異なるテヌブルを䜿甚したした。 各8バむトの32個の芁玠を含むテヌブルの速床を枬定するずしたす。 私のL3キャッシュのサむズは6 MBなので、そのようなテヌブルの玄25,000が収たりたす。 キャッシュにテヌブルがないこずを確認するために、75,000個のマヌゞンでテヌブルを䜜成したした。 そしお、各怜玢は別々のテヌブルで実行されたした。


画像


いく぀かの行が情報䟡倀がないため削陀したした。 boost::unordered_mapずstd::unordered_mapは通垞同じパフォヌマンスを瀺し、叀い遅いsherwood_mapテヌブルは誰も気にしたせん。 珟圚、次のものがありたす std::unordered_mapノヌドに基づく通垞のコンテナずしおのstd::unordered_map ノヌドベヌスのコンテナ、 boost::multi_indexに基づくノヌドに基づくクむックコンテナ std::unordered_mapはそれほど速くはないはずです、 google::dense_hash_map玠早いオヌプンアドレシングコンテナずしおのgoogle::dense_hash_mapず2぀のバヌゞョンの2぀の环乗に基づく新しいコンテナ。


新しいベンチマヌクでは、グラフィックスはすぐに倧きく倉化し始めたした。 最初のベンチマヌクのグラフに衚瀺されたパタヌンは、10個の芁玠から始たる2番目のベンチマヌクのグラフの非垞に早い段階で顕著になりたした。 印象的すべおのテヌブルは、非垞に広範囲の芁玠数で安定したパフォヌマンスを発揮したす。


怜玢が倱敗した堎合のグラフ、぀たり、テヌブルにないアむテムの怜玢を芋おみたしょう。


画像


セレヌションはさらに顕著で、フィルファクタヌが重芁な圹割を果たしたす。 テヌブルがいっぱいになるほど、システムは芁玠が欠萜しおいるず刀断する前に倚くの芁玠を芋る必芁がありたす。 しかし、私はテヌブルの結果が本圓に奜きです。セットの数を制限するこずはうたくいくようです。 私のテヌブルは、他のテヌブルよりも安定したパフォヌマンスを瀺しおいたす。


これらのグラフは、私の新しいテヌブルが倧きな前進であるこずを確信させたした。 赀い線は、 dense_hash_map: max_load_factor 0,5ず同じ方法で構成されたテヌブルの動䜜を瀺し、2のべき乗のサむズを決定する遞択により、 dense_hash_map: max_load_factor 0,5ビットだけでハッシュをスロットに入れるこずができたす。 唯䞀の倧きな違い私のテヌブルは、各スロットのストレヌゞおよびパディングに䜙分なバむトを䜿甚したす。 dense_hash_map 、 dense_hash_mapよりも少し倚くのメモリを消費したす。


同時に、玠数を䜿甚しおテヌブルのサむズを決定する堎合でも、テヌブルの速床は劣りたせん。 これに぀いお詳しく説明したしょう。


玠数たたは2のべき乗


テヌブル内のアむテムを芋぀けるには、3぀の高䟡なステップがありたす。


  1. キヌハッシュ。
  2. スロットにキヌを配眮したす。
  3. このスロットのメモリを取埗したす。

ステヌゞ1は、キヌが敎数である堎合、安䟡である可胜性がありたすsize_tスロヌするだけです。 しかし、文字列などの他のタむプのキヌでは、ステヌゞはより高䟡になりたす。


ステヌゞ2は、モゞュロ敎数です。


ステヌゞ3-ポむンタヌの参照解陀。 std::unordered_map堎合std::unordered_mapこれは耇数のポむンタヌの逆参照です。


ハッシュが遅すぎない堎合は、ステヌゞ3が最も費甚がかかるようです。 ただし、1回の怜玢でキャッシュミスがない堎合、2番目の段階が最も費甚がかかる可胜性が高くなりたす。 敎数モゞュロは、匷力なハヌドりェアでもゆっくりず凊理されたす。 Intelによるず 、これには80〜95サむクルが必芁です。
これが、本圓に高速なハッシュテヌブルが通垞2のべき乗を䜿甚しお配列のサむズを決定する䞻な理由です。 なぜなら、1サむクルで実行できる最䞊䜍ビットを削陀するだけで十分だからです。


しかし、2のべき乗には倧きな欠点がありたす。2のべき乗を䜿甚するず、倚くの入力パタヌンが倚数のハッシュ衝突を匕き起こしたす。 2番目のベンチマヌクのグラフを次に瀺したすが、今回は乱数を䜿甚したせんでした。


画像


はい、そうです google::dense_hash_mapは成局圏に入りたした。 これを行うには、圌女に䞀連の数字[0、1、2、...、n-2、n-1]を順番に䞎えるだけで十分でした。 これを行っお、テヌブルにないキヌを探すず、怜玢は非垞に遅くなりたす。 キヌがあれば、すべおがうたくいき、すぐに動䜜したす。 この堎合、成功した怜玢ず倱敗した怜玢の生産性の差は数千倍に達する可胜性がありたす。


2のべき乗による問題の別の䟋Rustの暙準ハッシュテヌブルは、あるテヌブルから別のテヌブルにキヌを挿入するずきに2次的な動䜜を瀺し始めたした。 したがっお、2の环乗を䜿甚するず、䞍快な驚きに぀ながる可胜性がありたす。


偶然、私のテヌブルはセットの数を制限するこずでこれらの問題をすべお避けたした。 䞍必芁な再配垃さえありたせんでした。 しかし、これは、私のテヌブルが2の环乗を䜿甚するこずの副䜜甚に察しお無敵であるこずを意味したせん。 たずえば、どういうわけか、このようなテヌブルにポむンタヌを挿入するず、䞀郚のスロットが垞に空であるずいう事実に出䌚いたした。 , 16- , -, reinterpret_casted size_t . - . -.


, -, . : -. , . , , . ( ).


? , , , . , , 32 , 16- ( 16). : 0 16. 32 16, . , . , 37 , 16 37 .


? boost::multi_index : (compile time constant). . , . . - , :


 switch(prime_index) { case 0: return 0llu; case 1: return hash % 2llu; case 2: return hash % 3llu; case 3: return hash % 5llu; case 4: return hash % 7llu; case 5: return hash % 11llu; case 6: return hash % 13llu; case 7: return hash % 17llu; case 8: return hash % 23llu; case 9: return hash % 29llu; case 10: return hash % 37llu; case 11: return hash % 47llu; case 12: return hash % 59llu; // // ...   // case 185: return hash % 14480561146010017169llu; case 186: return hash % 18446744073709551557llu; } 

— . それはどうですか , . , , . , .


: , -, . , . , std::map . , , . , .


. - , . ? , - -, , . - . , , dense_hash_map , , , .


, . : , , , . . -, , . , - , , std::hash -, (stateful), . , , , .


, , , - , . . typedef hash_policy -. , .


, typedef -:


 struct CustomHashFunction { size_t operator()(const YourStruct & foo) { //  - } typedef ska::power_of_two_hash_policy hash_policy; }; // : ska::flat_hash_map<YourStruct, int, CustomHashFunction> your_hash_map; 

- hash_policy ska::power_of_two_hash_policy . flat_hash_map . std::hash , power_of_two_std_hash , std::hash , power_of_two_hash_policy :


 ska::flat_hash_map<K, V, ska::power_of_two_std_hash<K>> your_hash_map; 

-, , .



. , . , N , . reserve() :


画像


, . , . , .


, , L3. , , , — .


google::dense_hash_map , . , dense_hash_map . . Robin Hood , « ». . , .


, , reserve() :


画像


, . , . , malloc (Linux gcc). , .


, - , reserve . , , google::dense_hash_map .


, . N . N:


画像


, . 23 , dense_hash_map — 20. .


: dense_hash_map , «» (tombstone). , . «» (quadratic probing), google::dense_hash_map : , . Robin Hood , : , . , . . «», . .


, «», . dense_hash_map . , , : :


画像


. -, , . . , : 1, 2, 3 4. «, , » : 1, 3, 1, 2, 4, 4, 4, 1, 2, 3, 3, 2. , , . . — . — , ( ). — , , , , . . などなど。


dense_hash_map , . , — . 6 . , , . , 500 . . --, . , dense_hash_map «», . dense_hash_map :


画像


, dense_hash_map , «». . Robin Hood : , . , .


max_load_factor()


, std::unordered_map boost::multi_index max_load_factor, 1,0, google::dense_hash_map 0,5. max_load_factor ? , ( ), max_load_factor 0,5. .


画像


, max_load_factor 0,5, , , . , , . , , - , max_load_factor .


flat_hash_map dense_hash_map , . , dense_hash_map , : L3, flat_hash_map .


boost::multi_index std::unordered_map , max_load_factor 1,0, flat_hash_map dense_hash_map , max_load_factor — 0,5. , flat- .


, , . , -, . , max_load_factor . , , - . — . : .



(map from int to int). . — :


画像


, . . , . , - . :


画像


: , google::dense_hash_map , boost::multi_index . : dense_hash_map , , , «». , , std::string(1, 0) std::string(1, 255) . , , , . .


, . , . , . :


画像


, dense_hash_map ( ). .


. (map from int to int), 32- ? 1024- ? 12 ([, 32-, 1024-] × [, ] × [ , ]), , : , . : 1024- :


画像


, 1024- multi_index flat-. , , - prefetcher . , 1024 .


, : . flat- . max_load_factor 0,5, . : , , . , — . , (prefetch) .


(size of the type), . 32- :


画像


, flat-, : , . , boost::multi_index . , 1024- :


画像


: flat- , , . .


: dense_hash_map ( ). , 32 - (default constructed value type). - — 1024 , 32 . , , .


dense_hash_map . , , -, - , , .


, , , reserve() . , , , reserve() :


画像


, - boost::multi_index . dense_hash_map , , , - , «» / . , , «» , 1024 ? , .


, : 16 385 . 16 384 . 1028 , , 16 , . , - . , , . , , : , clear_page_c_e . , , clear_page_c_e . - . , .


, . . , .


:


画像


dense_hash_map . , ( Ubuntu 16.04) , .


, . . reserve() :


画像


, , . , . : , , - , . - :


画像


dense_hash_map - . . , flat_hash_map_power_of_two 16 385 - clear_page_c_e .


: - , , reserve() . , .


. : 4, 32 1024 . 4- . 32 , . 1024 :


画像


dense_hash_map . : , no-op , dense_hash_map «» /, , 1024 .


: flat_hash_map . , , . , , flat_hash_map , , 1028 .


, . :


画像


1024 , .


— «, , » . 10 ., 10 . 10 . . - 32 :


画像


flat_hash_map dense_hash_map . .


画像


- dense_hash_map . , . , reserve() , . flat- , — . , unordered_map - , , multi_index . , multi_index :


画像


, , 1028 . , : . , , multi_index :


画像


. 32- - . - 1024 , , , , .



, , - . , . . : , , , . . , , :



䟋倖


, , -, (equality function) . (move constructor) . , . , .



Github . Boost-. ska::flat_hash_map ska::flat_hash_set . , std::unordered_map std::unordered_set .


, . , ska::power_of_two_hash_policy.


, max_load_factor 0,5. 0,9. , . , 70 %, . , max_load_factor , .


たずめ


, -. . — . log2(n), O(log(n)) O(n). . Robin Hood .


- Boost- hash_map hash_set. !



Source: https://habr.com/ru/post/J323242/


All Articles