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更高效?是的,抱歉。邮递