Python 有效的逐浮点字节乘法
在输入端,我有一个带符号的字节数组Python 有效的逐浮点字节乘法,python,algorithm,python-3.x,Python,Algorithm,Python 3.x,在输入端,我有一个带符号的字节数组barr(通常是小的尾数,但这可能并不重要)和一个浮点f,用于乘以barr 我的方法是将barr转换成一个整数val(使用int.from_bytes函数),将其相乘,执行溢出检查并在需要时“裁剪”相乘的val,然后将其转换回字节数组 def multiply(barr, f): val = int.from_bytes(barr, byteorder='little', signed=True) val *= f
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
def乘法(barr,f):
val=int.from_字节(barr,byteorder='little',signed=True)
val*=f
val=int(val)
val=cropInt(val,bitLen=barr.uu len_uuu()*8)
barr=val.to_字节(barr.\uu len\uuu(),byteorder='little',signed=True)
回程车
def cropInt(整数、位、有符号=真):
maxValue=(2**(bitLen-1)-1)如果有符号,则为else(2**(bitLen)-1)
minValue=-maxValue-1,如果签名为0
如果整数>最大值:
整数=最大值
如果整数<最小值:
整数=最小值
返回整数
但是,在处理大量数据时,此过程非常缓慢。有没有更好、更有效的方法呢?纯Python对任何数值计算都不起作用-因为每个数字都被视为一个对象,所以每个操作都涉及很多“隐藏”步骤 另一方面,如果使用适当的第三方库集,Python可以非常有效地进行数值计算 在您的情况下,sice性能很重要,您可以使用事实上的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))
请注意,本示例一次获取所有字节数据,而不是在传递原始“乘法”函数时一次获取一个字节数据。因此,您还必须将整数的位大小传递给它
行dtype=“%sint%d”%(“if signed else”,bitlen)
创建数据类型名称,NumPy根据传入的位数使用该名称。由于名称只是一个字符串,它会根据无符号的数据类型,插入一个添加或不添加“u”前缀的字符串,并将位数放在末尾。NumPy数据类型可在以下位置进行检查:
使用500000个8位有符号整数数组运行时,我得到以下计时结果:
在[99]:%time y=numpy_乘法(数据,1.7,8)
CPU时间:用户3.01毫秒,系统4.96毫秒,总计7.97毫秒
壁时间:7.38毫秒
在[100]中:%时间x=原始乘法(数据,1.7,8)
CPU时间:用户11.3秒,系统1.86毫秒,总计11.3秒
壁时间:11.3秒
(这是在修改函数以一次对所有字节进行操作之后)-如我在初稿中所述,加速1500倍。纯Python对任何数值计算都相当不利-因为由于每个数字都被视为一个对象,每个操作都涉及大量“隐藏”步骤 另一方面,如果使用适当的第三方库集,Python可以非常有效地进行数值计算 在您的情况下,sice性能很重要,您可以使用事实上的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))
请注意,本示例一次获取所有字节数据,而不是在传递原始“乘法”函数时一次获取一个字节数据。因此,您还必须将整数的位大小传递给它
行dtype=“%sint%d”%(“if signed else”,bitlen)
创建数据类型名称,NumPy根据传入的位数使用该名称。由于名称只是一个字符串,它会根据无符号的数据类型,插入一个添加或不添加“u”前缀的字符串,并将位数放在末尾。NumPy数据类型可在以下位置进行检查:
使用500000个8位有符号整数数组运行时,我得到以下计时结果:
在[99]:%time y=numpy_乘法(数据,1.7,8)
CPU时间:用户3.01毫秒,系统4.96毫秒,总计7.97毫秒
壁时间:7.38毫秒
在[100]中:%时间x=原始乘法(数据,1.7,8)
CPU时间:用户11.3秒,系统1.86毫秒,总计11.3秒
壁时间:11.3秒
(这是在修改函数以同时对所有字节进行操作之后)-如我在初稿中所述,加速1500倍。尝试使用模块解析字节序列。您还可以从
cropInt
函数中删除maxValue
和minValue
计算,以提高其速度。不幸的是,每个字节数组的长度可能不同,因此我每次都需要对其进行计数(但由于它们的长度基本相同,我可以为计算构建短期内存).在快速timeit
会话中,大部分时间用于int.From_bytes()
和int.to_bytes()
,这将很难使fasterDid更高效?是的,抱歉。Post及其标题编辑尝试使用模块解析字节序列。您还可以从cropInt
函数中删除maxValue
和minValue
计算,以提高其速度。不幸的是,每个字节数组的长度可能不同,因此我每次都需要对其进行计数(但由于它们的长度基本相同,我可以为计算构建短期内存).在快速timeit
会话中,大部分时间用于int.From_bytes()
和int.to_bytes()
,这将很难使fasterDid更高效?是的,抱歉。邮递