Ускорение отправки / записи массива Float32 с использованием плоских буферов - PullRequest
1 голос
/ 31 октября 2019

Я использую flatbuffers в Go для отправки массива с плавающей точкой 10000 по TCP между двумя портами на моей локальной машине. Я посылаю одно и то же сообщение в цикле, который только делает это. Скорость, которую я достигаю, составляет всего приблизительно 2 мс на сообщение, но в C ++ я достигаю приблизительно 140 мкс на сообщение. У меня есть следующая схема для моих сообщений flatbuffers

namespace MyModel;

table Features {
  data:[float32];
}

root_type Features;

, а затем в коде Go у меня есть builder := flatbuffers.NewBuilder(1024) и conn, err := net.Dial("tcp", endPoint), а после нескольких других вещей, которые я имею в цикле отправки:

builder.Reset()

MyModel.FeaturesStartDataVector(builder, nFloat32s)
for i := nFloat32s - 1; i >= 0; i-- {
    builder.PrependFloat32(data[i])
}
featuresData := builder.EndVector(nFloat32s)
MyModel.FeaturesStart(builder)
MyModel.FeaturesAddData(builder, featuresData)
features := MyModel.FeaturesEnd(builder)

builder.Finish(features)
msg := builder.FinishedBytes()
msgLen := make([]byte, 4)
flatbuffers.WriteUint32(msgLen, uint32(len(msg)))

conn.Write(msgLen)
conn.Write(msg)

Количество полученных сообщений и их содержание соответствуют сообщениям программы Python. Но это в 14 раз медленнее, чем когда я тестировал с использованием отправителя C ++ с данными, полученными той же самой программой Python. Я использую nFloats = 100000.

Профилирование показывает, что PrependFloat32 занимает много времени.

(pprof) top5 -cum
Showing nodes accounting for 2850ms, 61.29% of 4650ms total
Dropped 5 nodes (cum <= 23.25ms)
Showing top 5 nodes out of 18
      flat  flat%   sum%        cum   cum%
         0     0%     0%     4600ms 98.92%  main.main
     550ms 11.83% 11.83%     4600ms 98.92%  main.run
         0     0% 11.83%     4600ms 98.92%  runtime.main
    1140ms 24.52% 36.34%     3640ms 78.28%  github.com/google/flatbuffers/go.(*Builder).PrependFloat32
    1160ms 24.95% 61.29%     1790ms 38.49%  github.com/google/flatbuffers/go.(*Builder).Prep

Могу ли я сделать это быстрее?

(Конечно, для таких плоских данных я мог бы просто использовать необработанные сокеты, но позже я увеличу объем сообщения).

1 Ответ

1 голос
/ 31 октября 2019

То, что говорит @icza, стоит попробовать ... кроме того, возможно, у Go есть какая-то функция копирования массива, которую можно использовать для добавления всех поплавков одновременно, хотя для этого вам нужно будет добавить какое-то CreateFloatVectorфункция для застройщика. Уже есть CreateByteVector: https://github.com/google/flatbuffers/blob/521e255ad9656a213971b30ba1beeec395b2e27e/go/builder.go#L343

...