在我工作的项目中,我必须通过网络来回发送浮点数/双数组,我使用Boost.Asio作为网络内容,因为我需要通信是异步的,并且那里似乎是最好的(唯一真实的?)...
发送的数组是浮点数/双精度数,并且双方都知道该类型。 AFAIK,浮点存储标准可能存在问题+与longs / int,endians等相同的东西。
逻辑上,发送的数组是密集矩阵,由Eigen在一端处理,使用BLAS / [MKL | ATLAS]而在另一端,很可能需要其他用途,所以我要去以最通用的方式&这似乎是在数组周围传播。
关键要求是高性能和可移植性,因为客户端和服务器都可以在32/64位的任意组合上运行,并且通信非常紧张(实时监控,每秒刷新一次)客户端),因此序列化开销本身必须是最小的。
据我所知,到目前为止,这里要考虑的两个主要参与者是Boost.Serialization和Google的Protobuf。
BS的最大优点是我在项目中已经使用了很多Boost(尽管单元测试是在Google Test中),并且使用make_array()
序列化数组似乎非常简单。最重要的是表现。
从我发现的protobuf的优势是性能,所有的长凳似乎表明它在任何操作上都优于BS 10-20倍。我在protobuf文档中找不到的是在消息中添加一个数组。它使用重复的字段,根据我的理解,我必须在数组的每个元素上使用MsgObject.repeatedProp.Add(const T&)
,这意味着,即10k数组的10k调用,这看起来很有用也很昂贵。
关于如何解决这个问题的任何建议都会受到高度赞赏,因为我对C ++的经验有限,而且我最近才重新开始在长时间休息后写作...
答案 0 :(得分:1)
除了升级asio之外,您可能还想看看boost.MPI(消息传递接口)。这使用boost.serialization进行幕后序列化。
Boost.mpi discusses booost.serialization可能的性能优化。特别是使用
宏和mpi定义的宏
这些优化似乎运作良好,请参阅this图。
我从未使用过protobuff,所以我不能说这个。
答案 1 :(得分:1)
使用protobufs,如果使用“bytes”而不是“repeat int32”(或类似)对数组进行编码,则可以使10k数组的10k调用无效。 在你的代码中,如果你转换指针并使用memcpy,它通常会非常快。
答案 2 :(得分:0)
在github上有很好的例子。以下是进出协议缓冲区eigen和矩阵的一些可能资源:
这是HAL版本,它很简单,看起来效果很好:
Protobuf for storing a matrix:
package hal;
message MatrixMsg {
required uint32 rows = 1;
// columns deduced by division. Data stored as column major
repeated double data = 2 [packed=true];
}
message VectorMsg {
repeated double data = 1 [packed=true];
}
Loading into eigen and writing to protobuf:
#pragma once
#include <Eigen/Eigen>
#include <HAL/Messages.pb.h>
namespace hal {
inline void ReadMatrix(const MatrixMsg &msg, Eigen::MatrixXd* mat) {
mat->resize(msg.rows(),msg.data_size()/msg.rows());
for(int ii = 0 ; ii < msg.data_size() ; ii++){
mat->operator()(ii) = msg.data(ii);
}
}
inline void ReadVector(const VectorMsg &msg, Eigen::VectorXd* vec) {
vec->resize(msg.data_size());
for(int ii = 0 ; ii < msg.data_size() ; ii++){
vec->operator()(ii) = msg.data(ii);
}
}
inline void WriteMatrix(const Eigen::MatrixXd &mat, MatrixMsg *msg) {
msg->set_rows(mat.rows());
msg->mutable_data()->Reserve(mat.rows()*mat.cols());
for(int ii = 0 ; ii < mat.cols()*mat.rows() ; ii++){
msg->add_data(mat(ii));
}
}
inline void WriteVector(const Eigen::VectorXd &mat, VectorMsg *msg) {
msg->mutable_data()->Reserve(mat.rows());
for(int ii = 0 ; ii < mat.rows() ; ii++){
msg->add_data(mat(ii));
}
}
} // namespace hal
但是,如果您要跨图书馆进行此操作,则您需要考虑更多内容。还有一个库有一个很好的实现,其中有类型,宽度,高度的枚举,然后是一个字节数组,rowmajor / colmajor等。但我无法再找到它。这些必须被考虑并包含在protobuf中以与矩阵库兼容。对于有关如何执行此操作的一些想法,HAL image protobuf和image cpp可能会有所帮助,这可以从opencv源读取/写入,也可以将其视为矩阵。