我有一个numpy.array
,并希望将其内容向右旋转一位。我希望尽可能高效地执行此操作(在执行速度方面)。另请注意,数组的每个元素都是一个8位数字(np.uint8
)。旋转假定数组存储一个大数字,该大数字被分成大小为8比特的块,即,我不想自己旋转每个8比特元素,而是将整个数组一起旋转。
以下是一个消除任何混淆的示例:
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)
我的问题:在执行速度方面,有没有更好的方法来实现这种轮换?
谢谢大家。
答案 0 :(得分:1)
您可以通过减少临时数据的内存分配来加速“方法#2”:
function changetToX(input) {
return input.substring(0, 3) + 'xxx.xxx-' + input.substring(input.length - 2);
}
在我的系统上,使用1MB输入数组,这是原始速度的两倍,并产生相同的结果。
如果你愿意销毁输入,你可以消除其余两个分配中的一个(可能通过添加一个可选的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
参数,就像NumPy在例如out
中所做的那样)。