在输入上,我有一个带符号的字节数组barr
(通常是小端,但可能并不重要)和一个浮点f
与barr
相乘。
我的方法是将barr
转换为整数val
(使用int.from_bytes
函数),将其相乘,执行溢出检查以及"裁剪"如果需要,则乘以val
,然后将其转换回字节数组。
def multiply(barr, f):
val = int.from_bytes(barr, byteorder='little', signed=True)
val *= f
val = int (val)
val = cropInt(val, bitLen = barr.__len__()*8)
barr = val.to_bytes(barr.__len__(), byteorder='little', signed=True)
return barr
def cropInt(integer, bitLen, signed = True):
maxValue = (2**(bitLen-1)-1) if signed else (2**(bitLen)-1)
minValue = -maxValue-1 if signed else 0
if integer > maxValue:
integer = maxValue
if integer < minValue:
integer = minValue
return integer
但是,在处理大量数据时,此过程非常慢。有更好,更有效的方法吗?
答案 0 :(得分:4)
纯Python对于任何数值计算都是无用的 - 因为由于每个数字被视为一个对象,每个操作都涉及很多&#34;#34;步骤。
另一方面,如果使用适当的第三方库集合,Python可以非常有效地进行数值计算。
在你的情况下,sice性能很重要,你可以使用NumPy
- 用于数字处理的事实上的Python包。
使用它,铸造,乘法和重铸将在本机代码中一次完成(并且在知道比我更好的NumPy之后,可能步骤更少) - 并且应该给你3-4个订单的改进这项任务的速度:
import numpy as np
def multiply(all_bytes, f, bitlen, signed=True):
# Works for 8, 16, 32 and 64 bit integers:
dtype = "%sint%d" % ("" if signed else "", bitlen)
max_value = 2 ** (bitlen- (1 if signed else 0)) - 1
input_data = np.frombuffer(all_bytes, dtype=dtype)
processed = np.clip(input_data * f, 0, max_value)
return bytes(processed.astype(dtype))
请不要这个示例一次性获取所有字节数据,而不是一次传递给原始数据&#34;乘以&#34;功能。因此,你还必须以整数的大小来传递它。
dtype = "%sint%d" % ("" if signed else "", bitlen)
行创建数据类型名称,由NumPy根据传入的位数使用。即名称只是一个字符串,它插入一个字符串是否添加&#34 ; U&#34;前缀,取决于无符号的数据类型,并将位数放在末尾。可以在以下位置检查NumPy数据类型:https://docs.scipy.org/doc/numpy/user/basics.types.html
运行500000个8位有符号整数数组,我得到了这些时间:
在[99]中:%time y = numpy_multiply(data,1.7,8) CPU时间:用户3.01 ms,sys:4.96 ms,总计:7.97 ms 壁挂时间:7.38毫秒
在[100]中:%time x = original_multiply(data,1.7,8) CPU时间:用户11.3秒,sys:1.86毫秒,总计:11.3秒 停留时间:11.3秒
(这是在修改你的功能以便同时对所有字节进行操作之后) - 加速1500次,正如我在初稿中所述。