简体   繁体   English

有效字节乘浮点乘法

[英]Efficient byte by float multiplication

On the input I have a signed array of bytes barr (usually little endian, but that probably doesn't matter) and a float f to multiply barr with. 在输入中,我有一个带符号的字节barr数组(通常是小端字节,但这可能没关系)和一个浮点数f用于与barr乘以。

My approach is to convert barr into an integer val (using int.from_bytes function), multiply it, perform overflow checks and "crop" multiplied val if needed, then convert it back into an array of bytes. 我的方法是转换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

However this process is extremely slow when processing a large amount of data. 但是,当处理大量数据时,此过程非常慢。 Is there a better, more efficient way to do that? 有没有更好,更有效的方法呢?

Pure Python is rather innefective for any numeric calculations - because due to each number being treated as an object, each operation involves a lot of "under the hood" steps. 对于任何数值计算,纯Python都是无效的-因为由于每个数字都被视为对象,所以每个操作都涉及很多“幕后”步骤。

On the other hand, Python can be very effective for numeric calculation if you use the appropriate set of third party libraries. 另一方面,如果使用适当的第三方库集,Python对于数字计算可能非常有效。

In your case, sice performance matters, you can make use of NumPy - the de facto Python package for numeric processing. 就您的情况而言,重要的性能至关重要,您可以使用NumPy实际上是用于数字处理的Python程序包。

With it the casting, multiplication and recasting will be done in native code in one pass each (and after knowing better NumPy than I do, probably with even less steps) - and should give you an improvement of 3-4 orders of magnitude in speed for this task: 有了它,转换,乘法和重铸将分别在本机代码中一次完成(并且在比我更了解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))

Please not this example takes all your byte-data at once, not one at a time as you pass to your original "multiply" function. 请注意,此示例一次获取所有字节数据,而不是一次传递给原始的“乘”函数。 Threfore, you also have to pass it the size in bits of your integers. 因此,还必须将整数的大小传递给它。

The line that goes dtype = "%sint%d" % ("" if signed else "", bitlen) creates the data-type name, as used by NumPy from the number of bits passed in. SInce the name is just a string, it interpolates a string adding or not an "u" prefix, depending on the datatype being unsigned, and put the number of bits at the end. dtype = "%sint%d" % ("" if signed else "", bitlen)创建数据类型名称,该名称由NumPy从传入的位数中使用。因为该名称只是一个字符串,它会根据未签名的数据类型插入一个添加或不添加“ u”前缀的字符串,并将位数放在最后。 NumPy datatypes can be checked at: https://docs.scipy.org/doc/numpy/user/basics.types.html 可以在以下位置检查NumPy数据类型: https//docs.scipy.org/doc/numpy/user/basics.types.html

Running with an array of 500000 8bit signed integers I get these timings: 使用500000个8位有符号整数组成的数组运行,我得到以下计时:

In [99]: %time y = numpy_multiply(data, 1.7, 8) CPU times: user 3.01 ms, sys: 4.96 ms, total: 7.97 ms Wall time: 7.38 ms 在[99]中:%time y = numpy_multiply(data,1.7,8)CPU时间:用户3.01 ms,sys:4.96 ms,总计:7.97 ms挂墙时间:7.38 ms

In [100]: %time x = original_multiply(data, 1.7, 8) CPU times: user 11.3 s, sys: 1.86 ms, total: 11.3 s Wall time: 11.3 s 在[100]中:%time x = original_multiply(data,1.7,8)CPU时间:用户11.3 s,sys:1.86 ms,总计:11.3 s挂墙时间:11.3 s

(That is after modifying your function to operate on all bytes at a time as well) - an speedup of 1500 times, as I've stated on the first draft. (那是在修改您的函数以一次同时对所有字节进行操作之后)-加速了1500倍,正如我在初稿中所说的那样。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM