如何优化Numpy数组通过Protobuf消息的打包性能?
问题:将大型Numpy 3D点数组快速打包到Protobuf消息
背景
我有一个921000×3的numpy数组(共921k个3D点,每行对应一个点),需要打包进Protobuf消息,目前遇到性能瓶颈。使用Python 3.10和numpy 1.26.1,因为采用gRPC所以必须使用Protobuf,且可自主修改协议结构。
首次未优化实现
采用的Protobuf消息结构:
message Point { float x = 1; float y = 2; float z = 3; } message BodyData { int32 id = 1; repeated Point points = 2; }
打包代码(data为目标numpy数组):
body = BodyData() for row in data: body.points.append(Point(x=row[0], y=row[1], z=row[2]))
耗时:约1.6秒,速度严重不符合需求。
优化尝试:改用扁平数组结构
弃用Point嵌套结构,将所有点的X/Y/Z坐标合并成一维扁平数组传输,Protobuf消息结构调整为:
message Points { repeated float xyz = 1; } message BodyData { int32 id = 1; Points points = 2; }
先测试将numpy数组转换为列表的最快方式,结果如下:
# 耗时:80.1ms points = [] points.extend(data.flatten()) # 耗时:96.8ms points = [] points.extend(data.reshape((data.shape[0] * data.shape[1],))) # 耗时:76.5ms - 最快 points = [] points.extend(data.flatten().tolist())
但将该方式应用到Protobuf消息时,速度大幅下降:
# 耗时:436.0ms body = BodyData() body.points.xyz.extend(data.flatten().tolist())
当前困境
目前最快的打包方式耗时436ms,远未达到预期的约12ms性能目标,请问有没有更快的实现方案?
内容的提问来源于stack exchange,提问作者Jason C
相关产品推荐
相关产品推荐

