首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >加速蟒蛇的struct.unpack

加速蟒蛇的struct.unpack
EN

Stack Overflow用户
提问于 2016-04-22 14:54:38
回答 4查看 11K关注 0票数 13

我在努力加快我的剧本速度。它基本上读取一个pcap与Velodyne的LidarHDL-32信息,并允许我得到X,Y,Z和强度值。我使用python -m cProfile ./spTestPcapToLas.py对我的脚本进行了描述,它在readDataPacket()函数调用中花费的时间最多。在一个小测试(80 MB文件)中,解压缩部分大约占执行时间的56%。

我像这样调用readDataPacket函数(chunk引用pcap ):

代码语言:javascript
复制
packets = []
for packet in chunk:
    memoryView = memoryview(packet.raw())
    udpDestinationPort = unpack('!h', memoryView[36:38].tobytes())[0]

    if udpDestinationPort == 2368:
        packets += readDataPacket(memoryView)

readDataPacket()函数本身的定义如下:

代码语言:javascript
复制
def readDataPacket(memoryView):
    firingData = memoryView[42:]    
    firingDataStartingByte = 0    
    laserBlock = []

    for i in xrange(firingBlocks):
        rotational = unpack('<H', firingData[firingDataStartingByte+2:firingDataStartingByte+4])[0]        
        startingByte = firingDataStartingByte+4
        laser = []
        for j in xrange(lasers):   
            distanceInformation = unpack('<H', firingData[startingByte:(startingByte + 2)])[0] * 0.002
            intensity = unpack('<B', firingData[(startingByte + 2)])[0]   
            laser.append([distanceInformation, intensity])
            startingByte += 3
        firingDataStartingByte += 100
        laserBlock.append([rotational, laser])

    return laserBlock

对我如何加快进程有什么想法吗?顺便说一句,我用numpy来计算X,Y,Z,强度。

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2016-04-23 10:15:21

Numpy让你做得非常快。在这种情况下,我认为最简单的方法是直接使用ndarray构造函数:

代码语言:javascript
复制
import numpy as np

def with_numpy(buffer):
    # Construct ndarray with: shape, dtype, buffer, offset, strides.
    rotational = np.ndarray((firingBlocks,), '<H', buffer, 42+2, (100,))
    distance = np.ndarray((firingBlocks,lasers), '<H', buffer, 42+4, (100,3))
    intensity = np.ndarray((firingBlocks,lasers), '<B', buffer, 42+6, (100,3))
    return rotational, distance*0.002, intensity

这将返回单独的数组,而不是嵌套的列表,这应该更容易进一步处理。作为输入,它接受一个buffer对象(在Python2中)或任何公开缓冲区接口的内容。不幸的是,这取决于Python版本(2/3),您可以准确地使用哪些对象。但是这种方法非常快速:

代码语言:javascript
复制
import numpy as np

firingBlocks = 10**4
lasers = 32
packet_raw = np.random.bytes(42 + firingBlocks*100)

%timeit readDataPacket(memoryview(packet_raw))
# 1 loop, best of 3: 807 ms per loop
%timeit with_numpy(packet_raw)
# 100 loops, best of 3: 10.8 ms per loop
票数 14
EN

Stack Overflow用户

发布于 2016-04-22 15:20:35

提前编译Struct,以避免使用模块级方法包装代码。在环路外做,这样就不会重复支付建筑成本了。

代码语言:javascript
复制
unpack_ushort = struct.Struct('<H').unpack
unpack_ushort_byte = struct.Struct('<HB').unpack

Struct方法本身是在CPython中用C实现的(在解析格式字符串之后,模块级方法最终将委托给相同的工作),因此构建一次Struct并存储绑定方法可以节省大量的工作,特别是当解压缩少量的值时。

还可以通过将多个值一起解压缩来节省一些工作,而不是一次解压缩一个:

代码语言:javascript
复制
distanceInformation, intensity = unpack_ushort_byte(firingData[startingByte:startingByte + 3])
distanceInformation *= 0.002

作为Dan notes,您可以使用iter_unpack进一步改进这一点,这将进一步减少字节代码执行和小片操作的数量。

票数 11
EN

Stack Overflow用户

发布于 2020-09-12 14:12:53

对于你的特定情况,如果你能把你的循环放进一个无意义的呼叫中,那将是最快的。

也就是说,对于struct.unpack部分--如果您的数据发生了本机字节顺序,您可以使用memoryview.cast。以short为例,它比朴素的struct.unpack快约3倍,而逻辑上没有任何变化。

代码语言:javascript
复制
In [20]: st = struct.Struct("<H")

In [21]: %timeit struct.unpack("<H", buf[20:22])
1.45 µs ± 26.5 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

In [22]: %timeit st.unpack(buf[20:22])
778 ns ± 10.8 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

In [23]: %timeit buf.cast("H")[0]
447 ns ± 4.16 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/36797088

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档