キャッシュ除去アルゴリズムLRU実装原理についてお話しましょう

キャッシュ除去アルゴリズムLRU実装原理についてお話しましょう

[[315530]]

01. はじめに

データのクエリ速度を向上させるために、キャッシュがよく使用されます。キャッシュ容量には制限があるため、キャッシュ容量が上限に達すると、新しいデータを追加できるように、一部のデータを削除してスペースを確保する必要があります。キャッシュされたデータはランダムに削除することはできません。一般的に、特定のアルゴリズムに基づいてキャッシュされたデータを削除する必要があります。一般的な除去アルゴリズムには、LRU、LFU、FIFO などがあります。この記事では、LRU アルゴリズムについて説明します。

02. LRUの紹介

LRU  これは Least Recently Used の略です。このアルゴリズムは、最も最近使用されたデータをホット データと見なし、次回も高い確率で再び使用されるようにします。最近ほとんど使用されていないデータは、次回も使用されなくなる可能性があります。キャッシュ容量がいっぱいになると、最近あまり使用されていないデータが最初に削除されます。

キャッシュの内部データが以下のようになっていると仮定します。

ここでは、リストの最初のノードをヘッド ノード、最後のノードをテール ノードと呼びます。

キャッシュを呼び出してキー = 1 のデータを取得する場合、図に示すように、LRU アルゴリズムはノード 1 をヘッド ノードに移動する必要があり、他のノードは変更されません。

次にkey=8のノードを挿入します。このときキャッシュ容量が上限に達しているため、追加する前にデータを削除する必要があります。各クエリはデータをヘッド ノードに移動するため、クエリされていないデータはテール ノードに移動します。テールのデータは最もアクセスが少ないデータであると考えられるため、テール ノードのデータは削除されます。

次に、データをヘッドノードに直接追加します。

LRU アルゴリズムの具体的な手順の概要は次のとおりです。

  • 新しいデータはリストの先頭に直接挿入されます
  • キャッシュデータがヒットし、データがリストの先頭に移動される
  • キャッシュがいっぱいになったら、リストの末尾にあるデータを削除します。

03. LRUアルゴリズムの実装

上記の例からわかるように、LRU アルゴリズムではヘッド ノードを追加し、テール ノードを削除する必要があります。リンクリスト内のノードの追加/削除の時間計算量は O(1) であるため、ストレージ キャッシュ データ コンテナーとして非常に適しています。ただし、通常の一方向リンク リストは使用できません。一方向リンク リストには、いくつかの欠点があります。

  1. 任意のノードからデータを取得するたびに、最初のノードからトラバースする必要があり、その結果、ノードを取得する複雑さは O(N) になります。
  2. 中間ノードをヘッドノードに移動するには、中間ノードの前のノードの情報を知る必要があるため、一方向リンクリストを再度走査して情報を取得する必要があります。

上記の問題は、他のデータ構造を組み合わせることで解決できます。

ハッシュテーブルを使用してノードを格納すると、ノードを取得する複雑さは O(1) に削減されます。ノード移動の問題は、前のノード情報を記録するための先行ポインタをノードに追加することで解決できます。これにより、リンク リストが一方向リンク リストから双方向リンク リストに変更されます。

要約すると、図に二重リンクリストとハッシュテーブルの組み合わせを使用したデータ構造が示されています。

2 つの「センチネル」ノードは双方向リンク リストに意図的に追加されており、データの保存には使用されません。センチネル ノードを使用すると、ノードを追加/削除するときに境界ノードが存在しないかどうかを考慮する必要がなくなり、プログラミングの難易度が軽減され、コードの複雑さが軽減されます。

LRU アルゴリズムの実装コードは次のとおりです。簡略化のため、key と val は両方とも int 型とみなされます。

 public class LRUCache { Entry head, tail; int capacity; int size; Map<Integer, Entry> cache; public LRUCache(int capacity) { this.capacity = capacity; // 初始化链表initLinkedList(); size = 0; cache = new HashMap<>(capacity + 2); } /** * 如果节点不存在,返回-1.如果存在,将节点移动到头结点,并返回节点的数据。 * * @param key * @return */ public int get(int key) { Entry node = cache.get(key); if (node == null) { return -1; } // 存在移动节点moveToHead(node); return node.value; } /** * 将节点加入到头结点,如果容量已满,将会删除尾结点* * @param key * @param value */ public void put(int key, int value) { Entry node = cache.get(key); if (node != null) { node.value = value; moveToHead(node); return; } // 不存在。先加进去,再移除尾结点// 此时容量已满删除尾结点if (size == capacity) { Entry lastNode = tail.pre; deleteNode(lastNode); cache.remove(lastNode.key); size--; } // 加入头结点Entry newNode = new Entry(); newNode.key = key; newNode.value = value; addNode(newNode); cache.put(key, newNode); size++; } private void moveToHead(Entry node) { // 首先删除原来节点的关系deleteNode(node); addNode(node); } private void addNode(Entry node) { head.next.pre = node; node.next = head.next; node.pre = head; head.next = node; } private void deleteNode(Entry node) { node.pre.next = node.next; node.next.pre = node.pre; } public static class Entry { public Entry pre; public Entry next; public int key; public int value; public Entry(int key, int value) { this.key = key; this.value = value; } public Entry() { } } private void initLinkedList() { head = new Entry(); tail = new Entry(); head.next = tail; tail.pre = head; } public static void main(String[] args) { LRUCache cache = new LRUCache(2); cache.put(1, 1); cache.put(2, 2); System.out.println(cache.get(1)); cache.put(3, 3); System.out.println(cache.get(2)); }}

04. LRUアルゴリズムの分析

キャッシュ ヒット率は、キャッシュ システムの非常に重要な指標です。キャッシュ システムのキャッシュ ヒット率が低すぎると、クエリがデータベースに逆流し、データベースにかかる負荷が増加します。

上記の分析と組み合わせると、LRU アルゴリズムの長所と短所がわかります。

LRU アルゴリズムの利点は、実装が難しくなく、ホット データの場合、LRU 効率が非常に優れていることです。

LRU アルゴリズムの欠点は、履歴データのバッチ クエリなどの不定期のバッチ操作では、キャッシュ内の人気データがこれらの履歴データに置き換えられ、キャッシュ汚染が発生し、キャッシュ ヒット率が低下し、通常のデータ クエリが遅くなる可能性があることです。

05. LRUアルゴリズムの改善

以下のソリューションはMySQL InnoDB LRU改善アルゴリズムから派生したものです。

図に示すように、リンク リストをホット データ領域とコールド データ領域の 2 つの部分に分割します。

改善後、アルゴリズムのフローは次のようになります。

  1. アクセスされたデータがホット データ領域にある場合、以前の LRU アルゴリズムと同様に、ホット データ領域のヘッド ノードに移動されます。
  2. データを挿入するときに、キャッシュがいっぱいの場合は、末尾のノードにあるデータを削除します。次に 、データをコールド データ領域のヘッド ノードに挿入します
  3. コールド データ領域のデータにアクセスするたびに、データが 1 秒などの指定された時間以上キャッシュ内に存在していた場合は、ホット データ領域のヘッド ノードに移動されるという判断を行う必要があります。データが指定された時間より前の時間に存在する場合、位置は変更されません。

時々実行されるバッチ クエリの場合、データは単にコールド データ領域に送られ、すぐに削除されます。よく使用されるデータ領域のデータは影響を受けないため、LRU アルゴリズムのキャッシュ ヒット率が低下する問題が解決されます。

その他の改良された方法には、LRU-K、2Q、LIRS アルゴリズムなどがあります。興味のある学生はぜひチェックしてみてください。

<<:  AI技術は製薬業界の発展をどのように促進するのでしょうか?

>>:  流行中にどのようなホットなテクノロジーが使用されていますか? AI、5G、RTC、ビッグデータが登場

ブログ    

推薦する

紙画像の不正使用? AI: この道は私が塞いでいる

[[441681]]この記事はAI新メディアQuantum Bit(公開アカウントID:QbitAI...

...

ガンダムの運転をシミュレーションしますか? !優秀な学生が高度にシミュレーションされた運転体験ロボットシステムを発明し、白熱した議論を巻き起こした。

誰もがいつでもザクを操縦できるわけではありませんが、最近、優秀な大学生が「リモートコックピット」と呼...

C/C++アルゴリズム設計における任意のビット幅の使用

固定小数点アルゴリズムを開発する場合、設計機能、数値的に正確なモデリング、検証 (シミュレーション)...

医療における会話型 AI の 5 つの用途

パンデミックの影響で、医療業界は世界中で医師、看護師、その他の医療スタッフの深刻な不足に直面していま...

...

ケンブリッジ 2020 人工知能パノラマレポート、将来予測される 8 つの AI トレンド

ケンブリッジ大学の「AIパノラマレポート」2020年版がこのほど正式に発表された。ケンブリッジ大学の...

とてもかっこいいですね! Python で人工知能の最適化アルゴリズムを 5 分で理解する

概要勾配降下法は、ニューラル ネットワークでよく使われる最適化アルゴリズムの 1 つです。一般的に、...

サッカーボールとハゲ頭の区別がつかないAIがプレミアリーグのファンにまたもや嫌われる

スポーツにおける AI はどの程度信頼できないのでしょうか?先月、スコットランドサッカー選手権の試合...

2020年以降のAIトレンド

機械で書かれたニュース記事、AI 主導のサイバーセキュリティ、感情検出における重要な進歩など、201...

RNN モデルが Transformer の覇権に挑戦!ミストラル7Bに匹敵する1%のコストパフォーマンス、世界最多の100以上の言語をサポート

ビッグモデルが退化する中、トランスフォーマーの地位も次々と脅かされてきました。最近、RWKV は最新...

...

エッジコンピューティングとエッジ AI とは何ですか?この2つの違いは何でしょうか?

AIチップはクラウドとエッジに分かれています。クラウドチップは高いパフォーマンスが求められますが、...

...

...