Xav*_*ino 7 python performance numpy unpack lidar
我正在努力加快我的脚本.它基本上用Velodyne的Lidar HDL-32信息读取pcap文件,并允许我获得X,Y,Z和Intensity值.我已经使用了我的脚本python -m cProfile ./spTestPcapToLas.py,它在我的readDataPacket()函数调用中花费了大量的时间.在小测试(80 MB文件)中,解包部分占用大约56%的执行时间.
我这样调用readDataPacket函数(chunk指的是pcap文件):
packets = []
for packet in chunk:
memoryView = memoryview(packet.raw())
udpDestinationPort = unpack('!h', memoryView[36:38].tobytes())[0]
if udpDestinationPort == 2368:
packets += readDataPacket(memoryView)
Run Code Online (Sandbox Code Playgroud)
该readDataPacket()功能本身的定义是这样的:
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
Run Code Online (Sandbox Code Playgroud)
关于如何加快这个过程的任何想法?顺便说一句,我正在使用numpy进行X,Y,Z,Intensity计算.
Struct提前编译,以避免使用模块级方法的Python级别包装代码.在环路外进行,因此不会反复支付建设成本.
unpack_ushort = struct.Struct('<H').unpack
unpack_ushort_byte = struct.Struct('<HB').unpack
Run Code Online (Sandbox Code Playgroud)
的Struct本身C实现在CPython的(和模块级方法最终委托给相同的工作解析格式字符串之后),所以建立方法Struct一次并存储绑定方法节省了工作的一个非平凡量,拆包特别是当少量的价值观.
您还可以通过将多个值一起解压缩来保存一些工作,而不是一次解压缩一个:
distanceInformation, intensity = unpack_ushort_byte(firingData[startingByte:startingByte + 3])
distanceInformation *= 0.002
Run Code Online (Sandbox Code Playgroud)
正如Dan所说,你可以进一步改进这一点iter_unpack,这将进一步减少字节码执行量和小切片操作.
小智 7
Numpy让你很快就能做到这一点.在这种情况下,我认为最简单的方法是ndarray直接使用构造函数:
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
Run Code Online (Sandbox Code Playgroud)
这将返回单独的数组而不是嵌套列表,这应该更容易进一步处理.作为输入,它需要一个buffer对象(在Python 2中)或任何暴露缓冲区接口的东西.不幸的是,这取决于您的Python版本(2/3)您可以准确使用哪些对象.但这种方法非常快:
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
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
4045 次 |
| 最近记录: |