LRU (Least Recently Used) キャッシュアルゴリズムの実装

LRU (Least Recently Used) キャッシュアルゴリズムの実装

[[349478]]

LRU は Least Recently Used の略で、よく使われるページ置換アルゴリズムです。長い間使われていないページを削除します。実は、これも非常にシンプルで、人気のないページを適時に削除して、トイレを占領してリソースを無駄にしないようにするものです。

LRU は一般的なページ置換アルゴリズムです。コンピューティングでは、すべてのファイル操作をメモリ内で実行する必要があります。ただし、コンピュータのメモリのサイズは固定されているため、すべてのファイルをメモリにロードすることはできません。そのため、メモリに追加されるファイルを選択する戦略を開発する必要があります。

一般的なページ置換アルゴリズムは次のとおりです。

  • LRU 最近未使用
  • FIFO先入先出置換アルゴリズムはキューに似ている
  • OPT 最適順列アルゴリズム (理想)
  • NRU クロック置換アルゴリズム
  • LFU 最も使用頻度の低い置換アルゴリズム
  • PBA ページ バッファ アルゴリズム

LRU原則

LRU の設計原則は、データが最近の期間に頻繁にアクセスされた場合、将来も頻繁にアクセスされるというものです。つまり、頻繁にアクセスされるデータであれば、すぐにヒットするようにする必要があり、頻繁にアクセスされないデータであれば、容量が制限を超えたときに削除する必要があります。

コアはスタックを使用して操作を実行することであり、主にgetとputの2つの操作が含まれます。

得る

取得時に、スタック内に値がある場合は、その値のキーがスタックの先頭に移動され、ない場合は null が返されます。

置く

スタックがいっぱいでないとき、スタックに入れるキーがあれば、そのキーに対応する値を更新し、キーの値をスタックの一番上に持ってきます。入れるキーがない場合は、そのままスタックにプッシュします。

スタックがいっぱいになったとき、スタックに入れるキーがある場合は、このキーに対応する値を更新し、キーの値をスタックの一番上に置きます。スタックに入れるキーがない場合は、スタックの一番下の要素を削除し、値をスタックの一番上に置きます。

解決策:配列を維持し、get メソッドと put メソッドを提供し、最大数を制限します。

get を使用すると、要素を最近使用したものとしてマークし、最初の項目に昇格させることができます。 put はキー値を追加できますが、最大制限に達したかどうかを判断する必要があります。

達していない場合は、配列の最初の項目に直接挿入できます。 最大制限 max に達した場合は、データの末尾の要素を削除する必要があります。

  1. LRUCache cache = new LRUCache( 2 /* キャッシュ容量 */ );
  2.  
  3. キャッシュに1をセットします。
  4. キャッシュにデータを格納する。
  5. cache.get(1); // 1を返す
  6. cache.put(3, 3); // この操作によりキー2が無効になります
  7. cache.get(2); // -1 を返します (見つかりません)
  8. cache.put(4, 4); // この操作によりキー1が無効になります
  9. cache.get(1); // -1 を返します (見つかりません)
  10. cache.get(3); // 3 を返す
  11. cache.get(4); // 4を返す

LRUアルゴリズムの設計

上記の操作プロセスを分析すると、putメソッドとgetメソッドの時間計算量をO(1)にするために、キャッシュデータ構造に必要な条件として、高速検索、高速挿入、高速削除、および順序をまとめることができます。

明らかに、キャッシュは最近使用されたデータと長い間使用されていないデータを区別するためにソートされる必要があるため、キーがすでに存在するかどうかを確認するためにキャッシュを調べる必要があり、容量がいっぱいの場合は最後のデータを削除する必要があり、各アクセスではデータをキューの先頭に挿入する必要もあります。

では、上記の条件を同時に満たすデータ構造は何でしょうか? ハッシュ テーブルは検索が高速ですが、データには固定の順序がありません。リンク リストには順序があり、挿入と削除は高速ですが、検索は低速です。そこで、これらを組み合わせて、ハッシュ リンク リストという新しいデータ構造を形成します。

LRU キャッシュ アルゴリズムのコア データ構造は、二重リンク リストとハッシュ テーブルを組み合わせたハッシュ リストです。このデータ構造は次のようになります。

js実装

  • 特定のコードの一般的な解決策は、配列項目にキーと値のペアのオブジェクトを格納する配列を維持することです。毎回、キー値が配置されている配列インデックス操作を見つけるためにトラバースする必要があります。

leetCode 146 テストに合格しました。実行時間: 720 ミリ秒。メモリ使用量: 58.5 MB。

  1. 関数LRUCache(容量) {
  2. this.capacity = capacity; // 最大制限
  3. this.cache = [];
  4. };
  5.  
  6. /**
  7. * @param {数値}キー 
  8. * @return {数値}
  9. */
  10. LRUCache.prototype.get =関数(キー) {
  11. index = this.cache.findIndex((item) => item.key === key )とします。
  12. if (インデックス=== -1 ) {
  13. -1 を返します
  14. }
  15. // この要素を削除し、配列の最初の項目に挿入します
  16. 値を this.cache[インデックス].value とします。
  17. this.cache.splice(インデックス, 1);
  18. this.cache.unshift({
  19. 価値、
  20. });
  21. 戻り値;
  22. };
  23.  
  24. /**
  25. * @param {数値}キー 
  26. * @param {数値} 値
  27. * @return {void}
  28. */
  29. LRUCache.prototype.put =関数(キー、値) {
  30. index = this.cache.findIndex((item) => item.key === key )とします。
  31. // 挿入したいデータは既に存在するので、それを昇格するだけです
  32. if (インデックス> -1 ) {
  33. this.cache.splice(インデックス, 1);
  34. }そうでない場合 (this.cache.length >= this.capacity) {
  35. // 最大制限に達した場合は、最初に最も長い間使用されていないものを削除します
  36. this.cache.pop();
  37. }
  38. this.cache.unshift({キー、値 });
  39. };

実際には、上記のアプローチにはバリエーションがあります。オブジェクトを使用してキーと値のペアを保存し、配列を使用してキーの順序を保存できます。

  • 高度な要件 O(1)

時間の計算量は O(1) なので、配列を走査してキー値を見つけることはできません。 ES6 の Map を使用するとこの問題を解決できます。Map はキーと値のペアを維持できるだけでなく、挿入順序も記憶できるためです。

  1. 関数LRUCache(容量) {
  2. this.cache = 新しい Map();
  3. this.capacity = capacity; // 最大制限
  4. };
  5.  
  6. LRUCache.prototype.get =関数(キー) {
  7. if (this.cache.has(キー)) {
  8. // 存在する場合は更新する
  9. temp = this.cache.get(キー) とします。
  10. this.cache.delete (キー) ;
  11. this.cache.set (キー temp ) ;
  12. 戻る 温度;
  13. }
  14. -1 を返します
  15. };
  16.  
  17. LRUCache.prototype.put =関数(キー、値) {
  18. if (this.cache.has(キー)) {
  19. // 存在する場合は更新します(削除してから追加します)
  20. this.cache.delete (キー) ;
  21. }そうでない場合 (this.cache.size > = this.capacity) {
  22. // 存在しない場合は追加します
  23. // キャッシュが最大値を超えた場合は、最近使用されていないものを削除します
  24. this.cache.delete (this.cache.keys(). next ().value);
  25. }
  26. this.cache.set (キー、値 );
  27. };

<<:  自動運転技術が盛んに進歩していますが、実際に道路上で実用化されるまでにはどれくらい時間がかかるのでしょうか?

>>:  ニューラルネットワークの内部はどのようになっているのでしょうか?

ブログ    

推薦する

GPT-3 ハイパーパラメータは単一の GPU で解決できます。まず小さなモデルをトレーニングし、ワンクリックで移行します

この記事はAI新メディアQuantum Bit(公開アカウントID:QbitAI)より許可を得て転載...

モノのインターネットにおける人工知能の主要技術と手法

人工知能は、IoT の機能を実現する上で重要な役割を果たします。 AI と IoT の融合を推進し、...

大規模モデルをより強力にするには、検索拡張生成を使用します。ここでは、Python による実装手順を示します。

この記事では、まず RAG の概念と理論に焦点を当てます。次に、オーケストレーション用の LangC...

...

LLaMA、BERT などの導入課題を解決: 初の 4 ビット浮動小数点量子化 LLM が登場

大規模言語モデル (LLM) 圧縮は常に大きな注目を集めています。トレーニング後の量子化は、一般的に...

バーチャル試着室テクノロジーの仕組み

[51CTO.com クイック翻訳]テクノロジーの進歩と発展により、バーチャル試着室が人々の生活に入...

...

英国最高裁:特許の「発明者」は人工知能ではなく自然人でなければならない

ロイター通信は12月21日、現地時間20日に発表された英国最高裁判所の判決で、米国のコンピューター科...

...

...

...

人工知能はビッグデータの保存と管理の効率をどのように向上させるのでしょうか?

ビッグデータのソースが多数存在し、企業が利用できるデータの量も増加しているため、ストレージ管理者にと...

ビッグデータに責任を負わせないでください。スモールデータをうまく活用する方が効果的かもしれません。

誰もがビッグ データについて語っていますが、大規模なデータ セットを処理するにはより多くのストレージ...