2017-03-25 53 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

相关问题