ASCIIマイクロコントローラーからのシリアルポート経由の値(このように見えます:AA FF BA 11 43 CFなど))を読み込んでいるプロジェクトがあります。入力がすぐに入力されます(38 2文字セット/秒)私はこの入力を取得し、それをすべての測定の実行リストに追加しています。
約5時間後、私のリストは約855000エントリに増えました。
リストが大きくなるほど、リストの操作が遅くなることを理解しています。私の意図は、このテストを24時間実行して、約3Mの結果が得られるようにすることです。
リストに追加してからlist.append()を追加するより効率的で高速な方法はありますか?
みんな、ありがとう。
リストが大きくなると、リストの操作が遅くなることを理解しています。
それは一般的には当てはまりません。 Pythonのリストは、名前にもかかわらず、リンクされたリストではなく配列です。配列に対してO(n)である操作があります(コピーおよび検索、例)しかし、あなたはこれらのどれも使用していないようです。経験則として:それが広く使用されており、慣用的である場合、一部の賢い人々はそれを行うためにスマートな方法を選びました。list.append
は広く-組み込み関数を使用(そして、基になるC関数は、リスト内包表記など、他の場所でも使用されます)より速い方法があった場合、それは既に使用されています。
ソースコード を調べるとわかるように、リストは全体に割り当てられています。つまり、リストのサイズが変更されると、1つのアイテムに必要以上に割り当てられるため、別のサイズ変更をせずに次のn個のアイテムを追加できます( O(n))です。サイズの増加は一定ではなく、リストのサイズに比例するため、リストが大きくなるほどサイズ変更はまれになります。以下は、割り当て超過を決定するlistobject.c:list_resize
のスニペットです。
/* This over-allocates proportional to the list size, making room
* for additional growth. The over-allocation is mild, but is
* enough to give linear-time amortized behavior over a long
* sequence of appends() in the presence of a poorly-performing
* system realloc().
* The growth pattern is: 0, 4, 8, 16, 25, 35, 46, 58, 72, 88, ...
*/
new_allocated = (newsize >> 3) + (newsize < 9 ? 3 : 6);
Mark Ransomが指摘しているように、古いPythonバージョン(<2.7、3.0)には、GCを妨害するバグがあります。そのようなPythonバージョンがある場合、gcを無効にしたい場合があります。生成されたガベージが多すぎて(参照カウントがずれて)できない場合は、運が悪いです。
検討する必要があるのは、収集されたデータをファイルに書き込むことです。パフォーマンスに影響するかどうかはわかりません(または本当に気にします)が、電源が切れてもすべてのデータが失われないようにするのに役立ちます。すべてのデータを取得したら、それをファイルから吸い出して、リスト、配列、または派手な行列などの処理のためにジャムすることができます。
pythonリストへの追加には一定のコストがあります。リスト内のアイテムの数には影響されません(理論的には)。実際には、リストの追加が遅くなると、メモリとシステムがスワッピングを開始します。
http://wiki.python.org/moin/TimeComplexity
実際にリストに追加する理由を理解しておくと役に立ちます。アイテムをどうするつもりですか。それらのすべてが必要ない場合は、リングバッファーを作成できます。計算を行う必要がない場合は、リストをファイルに書き込むなどできます。
配列の長さを知っていて、16進コードをintに変換できる場合は、numpyを使用する方が速い場合があります。
import numpy
a = numpy.zeros(3000000, numpy.int32)
for i in range(3000000):
a[i] = int(scanHexFromSerial(),16)
これにより、整数の配列が残ります(hex()を使用して16進数に変換し直すことができます)。ただし、アプリケーションによっては、問題なく動作する場合があります。
まず、1秒あたり38個の2文字セット、1ストップビット、8データビット、パリティなしは、わずか760ボーであり、まったく高速ではありません。
とにかく、私の提案は、リストが大きすぎるのが心配な場合や、1つの巨大なリストを使用したくない場合は、リストが特定のサイズに達したらディスクに保存し、新しいリストを開始するだけです。すべてのデータを取得し、データの受信が完了したら、すべてのリストを1つに結合します。
サブリストを完全にスキップしてnmichaelsの提案にそのまま従うこともできますが、取得したデータをファイルに書き込み、小さな循環バッファーを使用して、まだ書き込まれていない受信データを保持します。