2015-01-07 8 views
7

私は、ハードウェアデバイスから一連のint32を読み込み、大規模なデータ構造の一部としてint配列に格納してから、リモートTCP/IP上のシステム。だから、私は定義されたものの束を使って単純なデータ構造体を使用していましたが、今これをプロトコルバッファを使うように変換したいと思います。 私はproto buffの要素として "繰り返しint32データ"を使用することを考えていました。しかし、私はこのようなループを使用しないようにしたい:整数配列を送信するC++プロトコルバッファ

int hardware_data[1000]; // An array that holds the data read from the hardware 
for(int i=0; i< sizeof(hardware_data); i++) 
{ 
    proto.add_data(hardware_data[i]); 
} 

Iいただきたいむしろちょうど[]配列(ゼロコピー方式)既存のhardware_dataを指し、このようなプロトバフを作るよう、効率的な方法を使用します、またはhardware_dataからproto.dataへのmemcpyを使用します。

私はmemcpy()を設定する方法を理解していますが、proto.dataの「配列」に含まれる要素の数はproto buffにどのように認識されますか? proto.data_size()を使用して要素数を取得できますか? ハードウェアの読み込みから送信するためにproto buffにデータを移動する効率的な方法はありますか? これを行うより良い方法はありますか?

Kerrik、 私はゼロコピーAPIを知らなかった。ここに私の原型の定義があります:

message hardware_data 
{ 
optional Lob      lob    = 1; 
optional int32     taskSeqNum  = 2; 
optional int32     secondsOfDay = 3; 
optional float     IQOutRateKhz = 4; 
optional float     IQBwKhz   = 5; 
optional int32     tStart   = 6; 
optional int32     tOffset   = 7; 
optional float     collectionTime = 8; 
optional int32     numSamples  = 9; 
optional int32     chunk   = 10; 
optional int32     dimSize   = 11; 
repeated int32     data   = 12 [packed=true]; 
} 

私はこのproto buffの定義にどのようにゼロコピーが再生されるのか分かりません。

+0

[ゼロコピーAPI](https://developers.google.com/protocol-buffers/docs/reference/cpp/google.protobuf.io.zero_copy_stream)のどの部分が不適切ですか? –

+2

'sizeof'演算子は、データ構造体のサイズを* bytes *で返します。したがって、int型の1000項目の配列ではおそらく4000であり、ループは配列の実際の終わりをはるかに超えてしまい、未定義の動作を引き起こします。配列の項目数*を計算するには、 'sizeof(hadware_data)/ sizeof(hardware_data [0])'を使用します。 – CiaPan

+0

もちろん....私はそれをサンプルコードとして配置しました。あなたのコメントは正しいものの、プロトコルバッファの使い方の質問には何も答えません。 – rbwilliams

答えて

1

ワイヤでは、パックされた繰り返しint32が一連のvarintとしてエンコードされます。 varintは可変幅のエンコーディングであり、小さい値の方がより少ないスペースを使用します。もちろん、これはデータが配列内でどのように表現されるかではないため、メッセージゼロコピーに埋め込むことは実際には不可能です。

実際には、現在2つのコピーを作成していますが、そのうちの1つを削除できます。 int hardware_data[1000]を直接割り当てる代わりに、データを直接google::protobuf::RepeatedField<int>に貼り付けることを検討してください。あなたはそのコピーせずにメッセージにそのデータを移動するSwap()の巧妙な使用を行うことができます。

RepeatedField<int> hardware_data; 
hardware_data.Reserve(expected_size); 
get_data_somehow(&hardware_data); 

// later 
proto.mutable_data()->Swap(&hardware_data); 

メッセージをシリアライズした後、あなたは、さらにフィールドバック)(スワップすることを望むかもしれないあなたができるように、すでに予約されていたメモリを再利用してください。

メッセージのシリアライズでは、データのエンコードの一環としてデータをコピーする必要があります。たとえエンコーディングをpacked repeated fixed32(実際には32ビット整数としてコード化されています)に変更したとしても、メモリを直接使用するようにライブラリを納得させる方法はありません。

+0

ありがとうケントン、私はプロトのバフを使用するための効率的な方法はないようです。これは組み込みプラットフォームであることに注意してください。私はリアルタイムで多くの電波スペクトルデータを処理しています。だからパフォーマンスは私にとっては重要な問題です。ある場所から別の場所へのデータの過度のコピーは非常に無駄です。私はこれがproto buffsを使用しないのに十分な理由だと思う。 – rbwilliams

+0

@rbwilliams:C++のprotobufライブラリはおそらく、組み込み環境で使用するにはあまりにも多くの割り当てを行うと思います。 protobuf-cを見て、それが良いかどうかを確認することができます。あるいは、あなたは[Cap'n Proto](https://capnproto.org)にもっと運があるかもしれません。これはすべてコピーを避けることです。 Cap'n Protoは外部配列を現在メッセージに「追加」することは許可していませんが、追加するのは非常に簡単で、必要な場合は喜んでできます。 (私はProtobuf C++ライブラリとCap'n Protoの両方の著者です。) –