2017-03-25 55 views
1

我有一個numpy.array,並且想將其內容向右旋轉一點。我希望儘可能高效地執行此操作(以執行速度而言)。另請注意,陣列的每個元素都是一個8位數字(np.uint8)。循環假定數組存儲一個大數字,它被分割成8位大小的數據塊,即我不想每個8位元素本身旋轉,而是整個數組一起旋轉。將numpy.array向右旋轉一位

這裏是消除任何混亂的例子:

a = numpy.array([0b00000000, 0b00000001]) 
# rotation should be performed globally 
# i.e., the result should be 
# rotate(a) == numpy.array([0b10000000, 0b00000000]) 

如何我試圖解決這個問題?

方法1:將輸入數組轉換爲二進制表示形式,並將元素的二進制字符串鏈接成一個大字符串。然後彈出最低有效位,並將其插入最高有效位之前。最後,將大字符串切成8位塊,將每個塊轉換爲np.uint8,並將其存儲在旋轉結果的相應位置。我想這個解決方案是正確的,但效率不高,特別是如果輸入數組很大。

方法2:我發現很難解釋的話的想法,所以我就嘗試使用下面的代碼片段傳達出來:

# Let w be the input array 
# read the least significant bits of every element in w 
# and store them into another array lsb 
mask = np.ones(shape=w.shape, dtype=np.int8) 
lsb = np.bitwise_and(w,mask) 
shiftedLsb = np.left_shift(np.roll(lsb, 1), 7) 
rotW = np.right_shift(w,1) 
rotationResult = np.bitwise_or(shiftedLsb, rotw) 

我的問題:是否有就執行速度而言,更好的方式來實現這種旋轉?

謝謝大家。

回答

1

您可以通過減少內存分配量爲臨時工加快你的「方法2」:

def method2a(w): 
    rotW = np.right_shift(w, 1) 
    lsb = np.bitwise_and(w, 1) 
    np.left_shift(lsb, 7, lsb) 
    rotW[0] |= lsb[-1] 
    rotW[1:] |= lsb[:-1] 
    return rotW 

在我的系統,具有1MB輸入數組,這是快兩倍,你原來,併產生相同的結果。

如果您願意銷燬輸入,則可以消除剩下的兩個分配中的一個(可能通過添加可選的out參數,因爲NumPy在例如left_shift()中)。

+1

謝謝。我花了一段時間才明白你的這一行'rotW [1:] | = lsb [: - 1]'(太聰明瞭)。據我所知,如果需要快速執行,應避免不必要的內存分配。 – user8420488483439

相關問題