通过 protobuf 消息传递 numpy 数组的更快方法

问题描述 投票:0回答:1

我有一个 921000 x 3 numpy 数组(921k 3D 点,每行一个点),我试图将其打包到 protobuf 消息中,但遇到了性能问题。我可以控制协议并可以根据需要更改它。我正在使用 Python 3.10 和 numpy 1.26.1。我使用协议缓冲区是因为我使用 gRPC。

对于第一次未优化的尝试,我使用了以下消息结构:

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 三元组的平面数组进行传输:

message Points {
    repeated float xyz = 1;
}

message BodyData {
    int32 id = 1;
    Points points = 2;
}

我做了一些性能测试,以确定将 2D numpy 数组附加到列表的最快方法,并得到以下结果:

# Time: 80.1ms
points = []
points.extend(data.flatten())

# Time: 96.8ms
points = []
points.extend(data.reshape((data.shape[0] * data.shape[1],)))

# Time: 76.5ms - FASTEST
points = []
points.extend(data.flatten().tolist())

由此我确定

.extend(data.flatten().tolist())
是最快的。

但是,当我将其应用于 protobuf 消息时,它的速度减慢了:

# Time: 436.0ms
body = BodyData()
body.points.xyz.extend(data.flatten().tolist())

因此,我能够弄清楚如何将 numpy 数组打包到任何 protobuf 消息中的最快速度是 436 毫秒(921000 个点)。

这远远低于我的性能目标,即每个副本约 12 毫秒。我不确定我是否可以接近这个目标,但是有什么方法可以更快地做到这一点吗?

python numpy performance protocol-buffers
1个回答
0
投票

如果您的目标只是通过 gRPC 将某些内容发送到您控制的另一个程序,那么您实际上不必将所有内容都转换为“本机”protobuf 消息;您可以使用 protobuf

bytes
字段来存储其他序列化格式,例如 numpy
tobytes()
输出或 Arrow。这样会快很多。

© www.soinside.com 2019 - 2024. All rights reserved.