2012-11-27 19 views
1

減慢我有以下功能上覆羽圖像到哈希值(使用PIL)的列表:Python的性能提高內存的使用

def _GetImageHash(image): 
    st = time.time() 
    image_list = list(image.getdata()) 
    (columns, rows) = image.size 
    hash_vals = [0]*rows 
    for i in xrange(0,rows): 
    hash_vals[i] = hash(tuple(image_list[i*columns:(i+1)*columns])) 
    print "_GetImageHash time taken: ", time.time() - st 
    return hash_vals, image_list 

在另一個函數,我把這種方法在許多圖像文件,並存儲結果列表。但是,我觀察到每次調用此函數計算散列值所花費的時間都會顯着增加。如果我改變調用的順序,它不會改變這種觀察到的行爲(所有圖像大小相同,所以在函數計算散列值時不應該有顯着差異)。事實上,如果我做的:

image1_hash, image1_list = _GetImageHash(image1) 
image2_hash, image2_list = _GetImageHash(image1) 
image3_hash, image3_list = _GetImageHash(image1) 
image4_hash, image4_list = _GetImageHash(image1) 
image5_hash, image5_list = _GetImageHash(image1) ... 

報告的時間是這樣的:

_GetImageHash time taken: 0.672996044159 
_GetImageHash time taken: 1.40435290337 
_GetImageHash time taken: 2.10946083069 
_GetImageHash time taken: 2.84965205193 
_GetImageHash time taken: 3.57753205299 
_GetImageHash time taken: 4.71754598618 
_GetImageHash time taken: 5.10348200798 
_GetImageHash time taken: 5.83603620529 
_GetImageHash time taken: 6.57408809662 
_GetImageHash time taken: 7.30649399757 
_GetImageHash time taken: 7.26073002815 
_GetImageHash time taken: 7.94218182564 

看來,這種情況正在發生,因爲我存儲的名單。但爲什麼這裏的內存使用會導致性能下降?可以做些什麼來解決這個問題,所以內存使用對時間性能沒有太大的影響?

+0

什麼是'哈希()'的定義? –

+2

雖然這與您的問題是正交的:使用['timeit.default_timer()'](http://docs.python.org/2/library/timeit.html#timeit.default_timer)來衡量性能計時;它會爲您的平臺在精度上做正確的事情。 –

回答

0

我不知道你的圖像有多大,但如果你認爲這是一個內存問題,我會開始檢查該進程正在使用多少內存。你可以在線找到一個配方來進行調用(如here),或者只是跟蹤操作系統進程監視器中的內存使用情況。

如果是內存使用情況,我會做的第一件事就是用更緊湊的東西替換列表版本image_list。 Numpy陣列是理想的,但即使是標準庫模塊array也應該有所幫助。

我說應該,因爲如果image_list中的值都是小整數(小於256),那麼Python使用的是更小,緊湊的存儲,而不是重新分配這些整數。它重新分配列表中的指針來保存它們。如果你讓你的數組保存4(8)字節值,那麼這將與32(64)位系統上的列表使用的指針大小相同。我沒有使用PIL,所以我不熟悉pil.Image.getdata的返回。

+0

圖像散列函數在運行時會消耗大量內存,即使對於尺寸適中的圖像也是如此。首先它會生成一個包含圖像中所有像素的列表,並返回它。它還使每行中的所有像素都成爲臨時元組。如果減速是一個內存問題,那麼在每個函數調用之後調用'gc.collect()'可能會有所幫助,並且很容易測試。 – martineau

1

你可以嘗試禁用垃圾收集器,

import gc 
gc.disable() 

#your code 

gc.enable()