2017-09-16 85 views
1

我有一個函數將整數轉換爲長度爲3的元組,直到現在我一直在爲循環和緩存進行嵌套,但它仍然是很慢。函數pre計算值並將它們緩存在列表中,然後用__getitem__做一些數學運算來確定返回哪個值。然後用不同的數字調用數百萬次。numpy矢量化從x * y數組到x * y * 3

我最近開始使用numpy,並且我想盡可能地加快這個過程。我做的初始優化(劃分整個numpy數組以匹配緩存長度,所以__getitem__可以被忽略)加速了15到3秒的一個例子,並且如果可能的話我想嘗試使用向量化。

唯一的問題是我無法弄清楚如何使用vectorize將w*h數組轉換爲w*h*3,並且想知道是否有人知道如何?我已經考慮添加一個額外的維度,但它似乎更像是一個重塑類型的東西。

下面是一些示例代碼:

>>> height, width = 2, 5 

>>> array = numpy.arange(width * height).reshape(height, width) 
[[0 1 2 3 4] 
[5 6 7 8 9]] 

>>> test_list = [(0, i, 0) for i in range(width * height)] 
>>> numpy.vectorize(test_list.__getitem__)(array) 
(array([[0, 0, 0, 0, 0], 
     [0, 0, 0, 0, 0]]), array([[0, 1, 2, 3, 4], 
     [5, 6, 7, 8, 9]]), array([[0, 0, 0, 0, 0], 
     [0, 0, 0, 0, 0]])) 

#expected = [[(0, 0, 0) (0, 1, 0) (0, 2, 0) (0, 3, 0) (0, 4, 0)] 
#   [(0, 5, 0) (0, 6, 0) (0, 7, 0) (0, 8, 0) (0, 9, 0)]] 
+0

'numpy.vectorize' **不會提高性能**。正如文檔所說,「矢量化函數主要是爲了方便,而不是爲了性能而提供的,實現本質上是一個for循環。」更一般地說,如果你正在查找的結果是一個*元組列表*,那麼可能'numpy'不是正確的工具, –

+0

numpy的轉換似乎對準備查找數組有幫助,可能是正確的,寫回到正常列表,我會測試它的速度與答案:) – Peter

+0

我不知道它是否會有所幫助,但請記住,numpy可以使用數組作爲索引。 – o11c

回答

1

你可以簡單地在這種情況下使用賦值:

>>> import numpy as np 
>>> height, width = 2, 5 
>>> array = np.arange(width * height).reshape(height, width) 
>>> res = np.zeros((height, width, 3), dtype=array.dtype) 
>>> res[:, :, 1].flat = array.ravel() 
>>> res 
array([[[0, 0, 0], 
     [0, 1, 0], 
     [0, 2, 0], 
     [0, 3, 0], 
     [0, 4, 0]], 

     [[0, 5, 0], 
     [0, 6, 0], 
     [0, 7, 0], 
     [0, 8, 0], 
     [0, 9, 0]]]) 

如果您想元組,你可能會更好過使用普通for循環,普通列表:

>>> lst = array.tolist() 
>>> res = [[(0, item, 0) for item in sublst] for sublst in lst] 
>>> res 
[[(0, 0, 0), (0, 1, 0), (0, 2, 0), (0, 3, 0), (0, 4, 0)], 
[(0, 5, 0), (0, 6, 0), (0, 7, 0), (0, 8, 0), (0, 9, 0)]] 

兩種方法都(可能)更快比np.vectorize這只是一個方便的功能,而不是表現。

+0

第一個沒有真正完成這項工作,因爲我仍然需要列表查找(我使用了'(0,i,0)'僅作爲一個例子),但第二個是偉大的。在1280x720的陣列上,緩存查找需要7秒,我的改進後的查找花費了1.24秒,您的'tolist()'花費了0.05秒,感謝:D – Peter