2011-03-22 41 views
19

實現一個系統,當涉及到繁重的數學提升時,我想盡可能少地執行。用於緩存的哈希Numpy對象的快速方法

我知道存在與numpy對象一起使用memoisation的問題,並且因此實現了一個lazy-key緩存以避免整個「過早優化」參數。

def magic(numpyarg,intarg): 
    key = str(numpyarg)+str(intarg) 

    try: 
     ret = self._cache[key] 
     return ret 
    except: 
     pass 

    ... here be dragons ... 
    self._cache[key]=value 
    return value 

但由於字符串轉換需要相當長的一段...

t=timeit.Timer("str(a)","import numpy;a=numpy.random.rand(10,10)") 
t.timeit(number=100000)/100000 = 0.00132s/call 

什麼人建議爲「更好的方式」來做到這一點?

+0

[如何在Python中哈希大對象(數據集)?](http://stackoverflow.com/questions/806151/how-to-hash-a-large-object-dataset-in-python ) – tacaswell 2014-03-19 16:43:10

回答

23

this answer借來的......所以我真的想這是一個重複:

>>> import hashlib 
>>> import numpy 
>>> a = numpy.random.rand(10, 100) 
>>> b = a.view(numpy.uint8) 
>>> hashlib.sha1(b).hexdigest() 
'15c61fba5c969e5ed12cee619551881be908f11b' 
>>> t=timeit.Timer("hashlib.sha1(a.view(numpy.uint8)).hexdigest()", 
        "import hashlib;import numpy;a=numpy.random.rand(10,10)") 
>>> t.timeit(number=10000)/10000 
2.5790500640869139e-05 
+3

不錯!對於多維數組,這會根據fortran或c是否連續而給出不同的散列(對於「相同」數組)。如果這是個問題,調用'np.ascontiguousarray'應該可以解決它。 – jorgeca 2014-01-27 16:00:24

+0

不確定爲什麼選擇已知的慢哈希函數'sha1'。 SHA-1可以儘量減少散列衝突,但速度很慢。對於速度,你需要像'murmurhash'或'xxhash'(後者聲稱更快)。 – 2015-08-05 10:06:26

+0

@CongMa,感謝您的額外信息。有很多選擇!但是你會注意到,這已經快了兩個數量級。而速度永遠不是唯一的擔憂。如果備選方案的速度只有百萬分之幾秒,那麼使用一個很好理解的散列值也是值得的。 – senderle 2015-08-08 11:24:01

2

對於小numpy的陣列也這可能是合適的:

tuple(map(float, a)) 

如果a是numpy的陣列。

+0

哦,是的,與列表相比,元組是可散列的! – 2017-10-01 14:48:22