8

Python セット コレクションを使用して、一意のオブジェクトを格納します。すべてのオブジェクトはオーバーライドさ__hash__れています。__eq__

このセットには、200,000 近くのオブジェクトが含まれています。セット自体は 4 GB 近くのメモリを必要とします。5 GB を超えるマシンでは正常に動作しますが、利用可能な RAM が 3 GB しかないマシンでスクリプトを実行する必要が生じました。

スクリプトを C# に書き直しました。実際には、同じソースから同じデータを読み取り、それをセット (HashSet) の CLR アナログに配置すると、4 GB ではなく 350 MB 近くかかりましたが、スクリプトの実行速度は比較的同じでした (約 40 秒) しかし、Python を使用する必要があります。

Q1: Python には「ディスク永続」セットまたはその他の回避策がありますか? hash/eq メソッドで使用される「キー」データのみをメモリに格納でき、それ以外はすべてディスクに永続化できると思います。または、Python には、システムで使用できるよりも多くのメモリを消費する可能性があるオブジェクトの一意のコレクションを作成するための他の回避策があるかもしれません。

Q2: あまり実用的ではない質問: なぜ python set は set にこれほど多くのメモリを必要とするのですか?

64ビットのUbuntu 12.10で標準のPython 2.7.3を使用しています

ありがとうございました。

Update1: スクリプトの機能:

  1. 多くの半構造化された JSON ドキュメントを読み取る (各 JSON は、それに関連する集約オブジェクトのコレクションを持つシリアル化されたオブジェクトで構成されます)

  2. 各 JSON ドキュメントを解析して、メイン オブジェクトと集約されたコレクションのオブジェクトを取得します。解析されたすべてのオブジェクトはセットに格納されます。セットは、一意のオブジェクトのみを格納するために使用されます。最初にデータベースを使用しましたが、データベースの一意の制約は x100-x1000 遅く動作します。すべての JSON ドキュメントは、1 ~ 8 の異なるオブジェクト タイプに解析されます。各オブジェクト タイプは独自のセットに格納され、一意のオブジェクトのみがメモリに保存されます。

  3. セットに格納されたすべてのデータは、一意の制約を持つリレーショナル データベースに保存されます。各セットは別々のデータベース テーブルに格納されます。

非構造化データを取得し、JSON ドキュメント内の集約されたオブジェクト コレクションから重複を削除し、構造化データをリレーショナル データベースに保存するスクリプトの全体的な考え方。

更新 2:

2 delnan: コードのすべての行にコメントを追加して、他のすべてのスタッフ (データの取得、解析、反復) を同じに保つ別のセットに追加しました - スクリプトが必要とするメモリは 4 GB 少なくなりました。

つまり、これらの 200K オブジェクトがセットに追加されると、大量のメモリを消費し始めるということです。オブジェクトは、TMDB からの単純な映画データです。ID、ジャンルのリスト、俳優、監督のリスト、その他の多くの映画の詳細、および場合によっては Wikipedia からの大きな映画の説明です。

4

3 に答える 3

6

最善の方法は、セットに格納するオブジェクトを小さくすることです。不要なフィールドが含まれている場合は、それらを削除してください。

一般的なオブジェクトのオーバーヘッドを減らすために__slots__、使用されるフィールドを宣言するためにも使用できます。

class Person(object):
   __slots__ = ['name', 'age']
   def __init__(self):
      self.name = 'jack'
      self.age = 99
于 2013-03-21T18:59:33.317 に答える
5

セットは確かに多くのメモリを使用しますが、リストはそうではありません。

>>> from sys import getsizeof
>>> a = range(100)
>>> b = set(a)
>>> getsizeof(a)
872
>>> getsizeof(b)
8424
>>>

セットを使用する唯一の理由が重複を防ぐことである場合は、代わりにリストを使用することをお勧めします。オブジェクトを追加する前に、オブジェクトが既にリストにあるかどうかをテストすることで、重複を防ぐことができます。セットの組み込みメカニズムを使用するよりも遅くなる可能性がありますが、使用するメモリは確実に少なくなります。

于 2014-03-23T10:58:45.320 に答える
3

__slots__を使用してメモリ使用量を減らしてみてください。

私が最後にこの問題を非常に多くのオブジェクトで抱えていたとき、使用__slots__するとメモリ使用量が 1/3 に減少しました。

これはあなたが面白いと思うかもしれないSOの質問です。__slots__

于 2013-03-21T18:59:22.653 に答える