浮点乘法的高效字节

时间:2016-11-08 12:17:39

标签: python algorithm python-3.x

在输入上,我有一个带符号的字节数组barr(通常是小端,但可能并不重要)和一个浮点fbarr相乘。

我的方法是将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

但是,在处理大量数据时,此过程非常慢。有更好,更有效的方法吗?

1 个答案:

答案 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次,正如我在初稿中所述。