[英]Why is lookup in dictionary much faster than two if-tests in Python?
我需要閱讀千兆字節的文本,所以我正在嘗試優化我的代碼。 這樣做時,我發現,對於我的問題,使用字典比if-tests更快。
check = {'R':'-', 'F':'+'}
seqs = ['R', 'F']*100
def check1():
for entry in seqs:
if entry == 'R':
strand = '-'
if entry == 'F':
strand = '+'
def check2():
for entry in seqs:
strand = check[entry]
使用ipythong的%timeit我發現在字典中查找的速度比使用兩個if-tests快兩倍:
In [63]: %timeit check1()
10000 loops, best of 3: 38.8 us per loop
In [64]: %timeit check2()
100000 loops, best of 3: 16.2 us per loop
由於if-tests是如此基本,我沒想到性能差異。 這是眾所周知的嗎? 任何人都可以解釋為什么會這樣嗎?
UPDATE
我檢查了上面的兩個函數以及下面的check3()如何影響我的實際代碼的運行時間,並且對總時間沒有影響。 因此,在現實世界的例子中,要么字典中的提升不是那么高,其中'R'和'F'值需要不斷地從文件中重新讀取,或者這段代碼不是我的瓶頸的一部分。
無論如何,謝謝你的答案!
你還沒有真正證明, if
測試,在字典中查找比兩個更快。 你所展示的是,查找特定字典比這兩個測試更快。
通常,字典查找需要幾個步驟:從密鑰生成哈希以找到潛在匹配,然后通過比較密鑰來測試潛在匹配。 如果存在哈希表沖突,有時可能需要進行多次比較。 如果你有用戶定義的鍵類,那么這兩個步驟都可能很慢,它們通常對字符串很快,但在一個特殊情況下它們真的非常快,你已經遇到了這種情況。
您的字典使用的短字符串與編譯時已知的標識符格式相匹配。 Python將有助於“實踐”你的字符串'R'和'F'。 由於您在測試中使用的字符串在編譯時也是已知的,因此它們將是完全相同的實例。 對字典查找的所有這些意味着,查找的專用版本用於僅具有字符串鍵的字典,哈希始終是預先計算的,並且通過比較地址來進行密鑰比較(至少在成功時和您的它永遠不會失敗的兩把鑰匙)。
你的真實代碼,我假設是從輸入讀取字符串,所以它不會有'R'的實習副本。 這意味着它需要計算每行輸入的哈希值。 地址不匹配,因此必須為每個測試調用字符串比較函數。 你仍然只對字符串鍵進行一些優化,至少它不必對可能不是字符串的對象進行通用比較。
if
語句對於對象類型一無所知,因此每次都會進行通用比較。
與許多VM代碼一樣,它主要歸結為涉及的VM操作碼數量。
您可以使用dis
檢查已組合的函數:
import dis
dis.dis(func)
在2.6.4中,check1需要大約15-20個操作碼(取決於代碼路徑),用於每個比較和分支。 check2只需7(在添加缺失的chedict
字典后,全局聲明)。
字典在Python中進行了大量優化; 查找是O(1)
- 它只是一個哈希表查找,因此只是一個“操作” - 使用if
測試序列(即O(n)
)獲得的操作數量的一半。
這會揭示一些事情:
def check3():
for entry in seqs:
if entry == 'R':
strand = '-'
else:
strand = '+'
它實際上比我的電腦上的check2()
更快。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.