2011-11-16 31 views
6

バイナリデータ文字列をPythonで数値に変換する最も速い方法は何ですか?Pythonでの高速バイナリデータ変換

私はstruct.unpack_from()を使用していますが、パフォーマンスの限界に達しています。

コンテキスト:入力ストリームは、バイナリデータとASCIIデータが混在しています。 ASCIIデータの変換はctypeを使用してCで行われます。 ctypesを使用してCでアンパックを実装すると、アンパックするときと同様のパフォーマンスが得られました。私の推測では、コールのオーバーヘッドはあまりにも大きな要因でした。私はネイティブなCのような強要方法を見つけることを望んでいました(しかしPython以外)。ほとんどの場合、このコードはすべてCに移動する必要があります。

ストリームはネットワークバイトオーダー(ビッグエンディアン)で、マシンはリトルエンディアンです。例えば、変換は次のようになります。

import struct 
network_stream = struct.pack('>I', 0x12345678) 
(converted_int,) = struct.unpack_from('>I', network_stream, 0) 

私は、バイナリ変換の一般的な場合よりも、ストリーム形式の取り扱いについてはあまり心配し、unpackにでも代替がある場合。たとえば、socket.ntohl()にはintが必要で、int()はバイナリデータ文字列を変換しません。

お寄せいただきありがとうございます!

+0

正確に何を開梱していますか?単なる数値の配列ですか? –

+0

残念ながら、それはシングルトンの混合ストリームです。内容はヘッダーで示されます。ほとんどの変換は4Bの整数と浮動小数点数です。 – CNK

+1

テストケースはここでうれしい – Triptych

答えて

2

スピードの問題はおそらくstruct.unpack_from()の実装にはありませんが、Pythonは辞書ルックアップ、オブジェクトの作成、関数やその他のタスクの呼び出しを行う必要があります。あなたはunpack_fromをインポートする直接ではなく、structモジュールからのたびにそれを取得することにより、これらの辞書検索のいずれかを排除することで、ほんの少し物事をスピードアップすることができます

$ python -m timeit -s "import struct; network_stream = struct.pack('>I', 0x12345678)" "(converted_int,) = struct.unpack_from('>I', network_stream, 0)" 
1000000 loops, best of 3: 0.277 usec per loop 

$ python -m timeit -s "import struct; from struct import unpack_from; network_stream = struct.pack('>I', 0x12345678)" "(converted_int,) = unpack_from('>I', network_stream, 0)" 
1000000 loops, best of 3: 0.258 usec per loop 

しかし、そのロジックを解析し、多くのことが必要である場合一度に1つの数値をアンパックする必要があり、データ全体を一括して解凍しないようにします。何を呼び出すかは関係ありません。おそらく、Cのようなオーバーヘッドの少ない言語でこの内部ループ全体を行う必要があります。

+0

興味深い考え。私は実際に 'from struct import *'を使用しました。あなたの例を模倣するためにこれを変換し、また約220M呼び出し以上の5%のパフォーマンスの違いを発見した。それを期待したことはありませんでした。ありがとう! – CNK

2

私の経験をもとに、あなたは、バイナリ変換のためのさまざまなツールのパフォーマンスを発見したように、コードはCに移動する必要があることが正しいです(例えばstructctypes)ほぼ同じ性能を持ちます。

Cythonは、PythonのC拡張を生成する最も簡単な方法です。

もう1つの簡単な方法は、CPythonを完全に放棄して、そのトレースJITを使用して高品質で低レベルのコードを生成できるpypyです。

より難しいがより直接的なアプローチは、プレーンなC拡張を書くことです。これは楽しいものではありませんが、難しいことではありません。

+0

これらの方法のうち、コールオーバーヘッドが最も低いと見積もる方法はどれですか? C拡張はctypesを使用するよりも効率的になるでしょうか? – CNK

+1

C拡張は、(リスト内またはイテレータ内の数値を返すごとに)一度に多くの変換を行う可能性があるため、常に勝つことができます。 * ctypes *アプローチには、変換ごとに1つの呼び出しの細分性があります。さらに、*すべての*データを必要としないため、C拡張は不要な値をスキップして、多くの変換/割り当て/インクリメント/比較/ジャンプ/デクリメントサイクルを保存できます。 –

関連する問題