[英]Improving speed of large dictionary in Python 3.4
因此,我正在研究具有1 000 000鍵的字典,我的任務是使它在3秒內(在Intel 2.4 GHz上)工作。 我嘗試對我的代碼進行性能分析,而while循環有很多成功之處,但是我想不出一種方法來使我的代碼在沒有它的情況下運行得更快。 有沒有一種方法可以改善我的代碼以使其更快地工作?
該代碼應該(並且這樣做,但是太慢)創建一個字典,其中的鍵都是從2到999999的整數,並且值是由序列模式制成的列表的長度。 模式是:如果整數是偶數,則將其除以2,如果整數是奇數且大於1,則將其乘以3並加1。這一直持續到達到數字1。
例如:3-> 10-> 5-> 16-> 8-> 4-> 2->1。此列表的長度是8。
碼:
import time
start = time.clock()
first = 2
last = 1000000
def function1(n,d):
if n/2 in d:
d[n] = d[n/2] + 1
if n not in d:
d[n] = 0
temp = n
while temp > 1:
if temp%2 == 0:
temp /= 2
d[n] += 1
else:
temp = 3*temp + 1
d[n] += 1
if temp in d:
d[n] += d[temp]
break
return d[n]
d={}
d[1]=1
d={key: function1(key,d) for key in range(first,last)}
print(time.clock() - start)
在我的系統上,您的代碼確實耗時超過3秒(在最近的2.3 GHz Intel Core i7 Macbook Pro上使用Python 3.4)。
我可以通過使用局部變量並避免兩次構建字典,在3秒內(減少2.65秒,減少12%)獲得它:
def function1(n,d):
if n/2 in d:
d[n] = d[n/2] + 1
return
if n not in d:
length = 0
temp = n
while temp > 1:
if temp%2 == 0:
temp //= 2
else:
temp = 3*temp + 1
length += 1
if temp in d:
length += d[temp]
break
d[n] = length
d={1: 1}
for key in range(first,last):
function1(key, d)
請注意,我使用局部length
變量,而不是一直從d[n]
讀取長度。 Python中的局部變量存儲在C數組中,從而避免了對鍵進行哈希處理和查找(可能包括哈希沖突)的麻煩。
我從/
(浮點除法)切換到//
(整數除法); 當您感興趣的只是整數結果時,無需處理小數點。
如果在字典中找到n/2
我也會返回 。 測試成功后,沒有必要測試n not in d
,因為我們剛剛添加了d[n]
。
字典的理解是完全多余的, function1()
已經就地更改了d
,因此構建新字典來替換現有結果沒有意義。
下一步是利用剛剛計算的temp
值序列。 當您從3
開始時,您將在此過程中計算其他幾個值。 所有這些都可以存儲在d
一旦你完成,所以你不必重新計算順序為10
, 5
, 16
, 8
和4
兩種 :
def function1(n,d):
if n not in d:
length = 0
seen = []
while n > 1:
seen.append(n)
if n % 2 == 0:
n //= 2
else:
n = 3 * n + 1
length += 1
if n in d:
length += d[n]
break
for num in seen:
d[num] = length
length -= 1
這里3
需要8個步驟,但是我們可以將7存儲為10
存儲為5
,依此類推。
我一共丟掉了if n/2 in d
測試, while
循環已經解決了這種情況。 由於if n not in d
塊中不再需要n
了,我將temp
完全刪除,然后繼續n
。
現在整個測試僅需1.75秒。
我相信一個有用的優化(可以在我的MB Air上使用Core i5在1.3 GHz上獲得2.4秒的性能,最好運行3次,使用Python 2.7.3; 3.4.1,2.7秒),這是避免“浪費”各種計算的最佳方法的temp
-保持它們不變可以讓您非常直接地計算它們的d
值。 這是我的版本...:
import time
start = time.clock()
first = 2
last = 1000000
def function1(n, d):
if n%2 == 0 and n//2 in d:
d[n] = d[n//2] + 1
if n not in d:
temp = n
intermediates = []
while temp > 1:
if temp%2 == 0:
temp //= 2
else:
temp = 3 * temp + 1
if temp in d:
d[n] = res = d[temp] + len(intermediates) + 1
for i, temp in enumerate(intermediates, 1):
d[temp] = res - i
return res
else:
intermediates.append(temp)
return d[n]
d={1: 1}
for k in range(first, last): function1(k, d)
print(time.clock() - start)
這是Collatz的猜想 。您可以檢查一些有關Internet的信息,一些有關Internet的C或C ++代碼,例如Python。 我認為您會發現人們以前做過的一些有用的功能。
您也可以使用numpy模塊,並可以使用它創建一些公式,我認為這樣做會更快。Numpy是一個可以輕松進行數學運算的模塊。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.