Python 中清除 LRU 快取


在本文中,我們將學習如何在 Python 中清除已實現的 LRU 快取。在深入程式碼方面之前,讓我們先了解一下什麼是 LRU 快取以及為什麼它如此受歡迎。

LRU 快取,也稱為最近最少使用快取,是一種廣泛應用於計算機科學的資料結構,透過減少訪問常用資料所需的時間來提高應用程式的效能。LRU 快取儲存有限數量的專案,並在快取已滿時刪除最近最少使用的專案。這使得最常用的專案保留在快取中並快速訪問,而不太常用的專案則被刪除以騰出空間供新專案使用。

LRU 快取在與檢索資料相關的成本很高的應用程式中特別有用,例如磁碟 I/O 或網路訪問。在這些情況下,將常用資料快取在記憶體中可以透過減少檢索資料所需的昂貴操作次數來顯著提高應用程式的效能。

LRU 快取廣泛應用於各種應用程式,包括資料庫、Web 伺服器、編譯器和作業系統。它在需要頻繁訪問大量資料的應用程式中特別有用,例如搜尋引擎和資料分析平臺。

在 Python 中與 LRU 快取互動

在 Python 3.2 及更高版本中,functools 模組包含一個強大的功能,允許程式設計師與 LRU 快取互動。此功能可以透過在類或函式定義上方放置一個裝飾器來使用。透過將此裝飾器應用於需要頻繁變數訪問和更改的函式,可以顯著提高函式的效能。

在處理需要處理大量資料或複雜計算的函式時,使用 LRU 快取可以大大加快執行時間。這是因為 LRU 快取將常用資料儲存在記憶體中,允許函式快速訪問和處理資料,而無需承擔耗時的 I/O 操作的成本。

透過利用 LRU 快取,Python 程式設計師可以減少應用程式的執行時間並提高其效能。這在處理大型應用程式或需要即時資料處理的應用程式時尤其重要,即使是效能上的微小改進也會帶來巨大的收益。

總之,Python 中的 functools 模組提供了一種強大的機制來與 LRU 快取互動。透過使用 LRU 快取,程式設計師可以透過減少昂貴的變數訪問和更改操作所需的時間來提高其應用程式的效能。LRU 快取的使用在需要即時資料處理或處理大量資料的應用程式中尤其有利。

現在我們對 LRU 快取有了一些瞭解,讓我們在 Python 中使用它。

Python 中 functools 模組的 cache clear() 方法可用於清除 LRU(最近最少使用)快取。

使用此技術可以完全清除快取。

示例程式碼片段

from functools import lru_cache

@lru_cache(maxsize=128)
def some_function(arg):
	# function implementation
	return result

# clear the cache
some_function.cache_clear()

解釋

在上面的示例中,some_function 使用 lru_cache 進行裝飾,這將建立一個最大大小為 128 的 LRU 快取。要清除快取,可以在函式物件上呼叫 cache_clear() 方法,這將刪除快取中的所有條目。

請注意,呼叫 cache_clear() 將清除所有引數的快取。如果要清除特定引數集的快取,可以使用其他快取實現,例如 functools.typed_lru_cache,它允許您使用帶引數的 cache_clear() 方法清除特定引數的快取。

現在讓我們使用上面的程式碼,並編寫一個可執行的示例。

考慮以下所示的程式碼。

示例

from functools import lru_cache

@lru_cache(maxsize=128)
def fibonacci(n):
	"""Return the nth Fibonacci number."""
	if n < 2:
    	return n
	return fibonacci(n-1) + fibonacci(n-2)

# Call the function with some arguments to populate the cache
print(fibonacci(10))  # Output: 55
print(fibonacci(15))  # Output: 610

# Clear the cache
fibonacci.cache_clear()

# Call the function again to see that it's recomputed
print(fibonacci(10))  # Output: 55

解釋

在此示例中,fibonacci 函式使用 lru_cache 來記憶其結果。快取的最大大小為 128,因此該函式將記住最近 128 次呼叫的結果。

我們首先使用一些引數呼叫該函式以填充快取。然後,我們使用 cache_clear() 方法清除快取。最後,我們再次使用相同的引數呼叫該函式以檢視它是重新計算而不是使用快取的結果。

要執行上述程式碼,我們需要執行以下所示的命令。

命令

python3 main.py

執行上述命令後,我們應該期望輸出類似於以下所示的輸出。

輸出

55
610
55

如果需要,我們也可以在上述程式碼中列印快取的當前狀態資訊,為此,我們需要使用 cache_info() 方法。

考慮以下所示的更新程式碼。

示例

from functools import lru_cache

@lru_cache(maxsize=128)
def fibonacci(n):
	"""Return the nth Fibonacci number."""
	if n < 2:
    	return n
	return fibonacci(n-1) + fibonacci(n-2)

# Call the function with some arguments to populate the cache
print(fibonacci(10))  # Output: 55
print(fibonacci(15))  # Output: 610

print(fibonacci.cache_info())

# Clear the cache
fibonacci.cache_clear()

# Call the function again to see that it's recomputed
print(fibonacci(10))  # Output: 55

print(fibonacci.cache_info())

解釋

上面的程式碼中的 @lru cache 裝飾器接受可選引數 maxsize,該引數指定快取的最大大小。

如果未定義 maxsize,則快取大小是無限的。

如果快取已滿,則會刪除最近最少使用的專案,以便為新專案騰出空間。

@lru cache 使用的快取位於函式物件本身中。

因此,快取對函式是私有的,並且不會由函式的其他版本共享。此外,這裡不同的部分是 cache_info() 方法,該方法用於列印有關 fibonacci 函式使用的 LRU 快取的資訊。這包括快取命中和未命中的次數,以及快取的大小。

要執行上述程式碼,我們需要執行以下所示的命令。

命令

python3 main.py

執行上述命令後,我們應該期望輸出類似於以下所示的輸出。

輸出

55
610
CacheInfo(hits=14, misses=16, maxsize=128, currsize=16)
55
CacheInfo(hits=8, misses=11, maxsize=128, currsize=11)

現在我們已經瞭解瞭如何清除快取,讓我們在另一個示例中使用它。

考慮以下所示的程式碼。

示例

from functools import lru_cache

@lru_cache(maxsize=128)
def edit_distance(s1, s2):
	"""
	Compute the edit distance between two strings using dynamic programming.
	"""
	if not s1:
    	return len(s2)
	elif not s2:
    	return len(s1)
	elif s1[0] == s2[0]:
    	return edit_distance(s1[1:], s2[1:])
	else:
    	d1 = edit_distance(s1[1:], s2) + 1  # deletion
    	d2 = edit_distance(s1, s2[1:]) + 1  # insertion
    	d3 = edit_distance(s1[1:], s2[1:]) + 1  # substitution
    	return min(d1, d2, d3)

# Call the function with some arguments to populate the cache
print(edit_distance("kitten", "sitting"))  # Output: 3
print(edit_distance("abcde", "vwxyz"))	# Output: 5

# Clear the cache
edit_distance.cache_clear()

# Call the function again to see that it's recomputed
print(edit_distance("kitten", "sitting"))  # Output: 3

解釋

在此示例中,edit_distance 函式使用動態規劃計算兩個字串之間的編輯距離。該函式是遞迴的,並具有三個基本情況:如果其中一個字串為空,則編輯距離是另一個字串的長度;如果兩個字串的第一個字元相同,則編輯距離是其餘字串之間的編輯距離;否則,編輯距離是三種可能操作的編輯距離的最小值:刪除、插入和替換。

為了提高函式的效能,我們使用 lru_cache 來記憶其結果。快取的最大大小為 128,因此該函式將記住最近 128 次呼叫的結果。這使我們能夠避免為相同的引數重新計算編輯距離。

我們首先使用一些引數呼叫該函式以填充快取。然後,我們使用 cache_clear() 方法清除快取。最後,我們再次使用相同的引數呼叫該函式以檢視它是重新計算而不是使用快取的結果。

請注意,edit_distance 函式只是一個示例,並且有更有效的方法來計算兩個字串之間的編輯距離(例如,使用 Wagner-Fischer 演算法)。此示例的目的是演示如何使用 lru_cache 來記憶遞迴函式的結果。

結論

總之,在某些情況下,清除 Python 中的 LRU(最近最少使用)快取對於管理記憶體並確保快取保持最新至關重要。LRU 快取是由 Python 的 functools 模組提供的內建快取機制,可用於根據函式的引數快取函式的結果。@lru_cache 裝飾器用於為函式啟用快取,並且可以指定 maxsize 來設定快取大小的限制。

可以使用裝飾的函式物件的 cache clear() 方法來清除 LRU 快取。透過清除所有快取的結果,此技術使快取保持最新,同時釋放記憶體。如果函式已更新或輸入資料頻繁更改,則可能需要清除快取。

總的來說,LRU 快取提供了一種簡單而有效的方法來提高 Python 函式的效能,尤其是那些計算密集型或多次使用相同引數呼叫的函式。在必要時清除快取有助於維持透過快取獲得的效能提升,並確保快取在減少計算時間方面保持有效。

更新於: 2023年8月2日

10K+ 次瀏覽

開啟您的 職業生涯

透過完成課程獲得認證

開始學習
廣告