Explicação detalhada do algoritmo LRU: estratégia de substituição de cache usada menos recentemente

Explicação detalhada do algoritmo LRU: estratégia de substituição de cache usada menos recentemente

introdução

Na ciência da computação, o cache é uma técnica de otimização comum usada para acelerar o acesso aos dados. Cache refere-se à memória de alta velocidade que armazena cópias de dados usados ​​recentemente para que possam ser acessados ​​rapidamente quando necessário. Em sistemas de computador, um dos tipos mais comuns de cache é o cache de memória, que inclui cache de páginas e cache de objetos. No cache, LRU (menos usado recentemente) é uma estratégia popular de substituição de cache. Este artigo apresentará detalhadamente o princípio e a implementação do algoritmo LRU.

Princípio do algoritmo LRU

O algoritmo LRU é baseado em um conceito simples: o princípio menos utilizado recentemente. O algoritmo acredita que os dados que foram usados ​​recentemente também provavelmente serão usados ​​novamente no futuro, enquanto os dados que não foram usados ​​por um longo período de tempo têm maior probabilidade de permanecer sem uso no futuro. Portanto, o algoritmo LRU utiliza uma estratégia de substituição de cache, ou seja, os dados que não são acessados ​​há mais tempo são eliminados do cache.

A ideia central do algoritmo LRU é manter um histórico ordenado de acesso aos dados. Quando um dado é acessado, ele é trazido para o início do histórico, enquanto os dados que não são acessados ​​há mais tempo ficam no final do histórico. Quando o espaço de cache for insuficiente, o algoritmo LRU selecionará os dados no final do registro histórico para substituição.

Método de implementação do algoritmo LRU

Use uma lista duplamente vinculada

Uma maneira comum de implementar o algoritmo LRU é usar uma lista duplamente vinculada. O topo da lista vinculada representa os dados acessados ​​mais recentemente, enquanto o final representa os dados que não foram acessados ​​há mais tempo. Sempre que os dados são acessados, eles podem ser movidos para o topo da lista vinculada. Se desejar inserir novos dados, mas o cache estiver cheio, você pode optar por excluir os dados no final da lista vinculada.

A seguir está o pseudocódigo para implementar o algoritmo LRU usando uma lista duplamente vinculada:

class LRUCache:

    def __init__(self, capacity: int):
        self.capacity = capacity
        self.cache = {}
        self.head = DoubleLinkedListNode()
        self.tail = DoubleLinkedListNode()
        self.head.next = self.tail
        self.tail.prev = self.head

    def get(self, key: int) -> int:
        if key in self.cache:
            node = self.cache[key]
            self._move_to_head(node)
            return node.value
        else:
            return -1

    def put(self, key: int, value: int) -> None:
        if key in self.cache:
            node = self.cache[key]
            node.value = value
            self._move_to_head(node)
        else:
            node = DoubleLinkedListNode(key, value)
            self.cache[key] = node
            self._add_to_head(node)
            if len(self.cache) > self.capacity:
                tail_node = self._remove_tail()
                del self.cache[tail_node.key]

    def _move_to_head(self, node: DoubleLinkedListNode) -> None:
        self._remove_node(node)
        self._add_to_head(node)

    def _add_to_head(self, node: DoubleLinkedListNode) -> None:
        node.prev = self.head
        node.next = self.head.next
        self.head.next.prev = node
        self.head.next = node

    def _remove_node(self, node: DoubleLinkedListNode) -> None:
        node.prev.next = node.next
        node.next.prev = node.prev

    def _remove_tail(self) -> DoubleLinkedListNode:
        tail_node = self.tail.prev
        self._remove_node(tail_node)
        return tail_node

class DoubleLinkedListNode:

    def __init__(self, key=None, value=None):
        self.key = key
        self.value = value
        self.prev = None
        self.next = None

Usando tabelas hash e filas

Outra forma de implementar o algoritmo LRU é usar tabelas hash e filas. As tabelas hash podem encontrar rapidamente nós com chaves específicas, enquanto as filas podem manter a ordem em que os dados são acessados.

A seguir está o pseudocódigo para implementar o algoritmo LRU usando tabelas hash e filas:

from collections import deque

class LRUCache:

    def __init__(self, capacity: int):
        self.capacity = capacity
        self.cache = {}
        self.queue = deque()

    def get(self, key: int) -> int:
        if key in self.cache:
            self.queue.remove(key)
            self.queue.append(key)
            return self.cache[key]
        else:
            return -1

    def put(self, key: int, value: int) -> None:
        if key in self.cache:
            self.queue.remove(key)
        elif len(self.cache) >= self.capacity:
            evicted_key = self.queue.popleft()
            del self.cache[evicted_key]
        self.cache[key] = value
        self.queue.append(key)

para concluir

O algoritmo LRU é uma estratégia de substituição de cache comumente usada que elimina dados com base no princípio dos dados usados ​​recentemente. Ao manter um histórico de acesso ordenado, o algoritmo LRU pode efetivamente melhorar a taxa de acertos do cache. Este artigo apresenta o princípio do algoritmo LRU e dois métodos comuns de implementação: usando listas duplamente vinculadas e usando tabelas hash e filas. Os leitores podem escolher seu próprio método para implementar o cache LRU com base em cenários de aplicativos específicos.

Acho que você gosta

Origin blog.csdn.net/m0_72410588/article/details/132867119
Recomendado
Clasificación