34

私は基本的に、既知のものに基づいて特定のことが起こる確率を調整するプログラムを持っています。pickleデータのファイルは、すでにDictionary オブジェクトとして に保存されていますDictionary.txt

問題は、プログラムを実行するたびに をDictionary.txt取り込み、辞書オブジェクトに変換し、編集して上書きすることDictionary.txtです。Dictionary.txtは 123 MBであるため、これはかなりメモリを集中的に使用します。ダンプするとMemoryErrorが発生しますが、プルするとすべて問題ないように見えます..

  • 編集を行うためのより良い (より効率的な) 方法はありますか? (おそらく、毎回ファイル全体を上書きする必要はありません)

  • gc(モジュールを介して) ガベージ コレクションを呼び出す方法はありますか? (私はすでにそれを介して自動的に有効にしていますgc.enable()

  • readlines()さらに、行ごとに読むことができることも知っています。プログラムに完全に完成した辞書オブジェクト ファイルが既にある場合、辞書を行ごとに段階的に編集する方法はありますか。

  • 他の解決策はありますか?

お時間をいただきありがとうございます。

4

9 に答える 9

17

私は というパッケージの作者ですklepto(そして の作者でもありますdill)。 klepto非常に単純な方法でオブジェクトを格納および取得するように構築されており、データベース、メモリ キャッシュ、およびディスク上のストレージへの単純な辞書インターフェイスを提供します。以下に、大きなオブジェクトを「ディレクトリ アーカイブ」に格納する方法を示します。これは、エントリごとに 1 つのファイルを持つファイル システム ディレクトリです。オブジェクトをシリアル化することを選択し (低速ですが、 を使用するdillため、ほとんどすべてのオブジェクトを格納できます)、キャッシュを選択します。メモリ キャッシュを使用すると、ディレクトリ アーカイブにすばやくアクセスできます。アーカイブ全体をメモリに保存する必要はありません。データベースやファイルとのやり取りは遅くなる可能性がありますが、メモリとのやり取りは高速です。また、アーカイブから好きなようにメモリ キャッシュを設定できます。

>>> import klepto
>>> d = klepto.archives.dir_archive('stuff', cached=True, serialized=True)
>>> d
dir_archive('stuff', {}, cached=True)
>>> import numpy
>>> # add three entries to the memory cache
>>> d['big1'] = numpy.arange(1000)
>>> d['big2'] = numpy.arange(1000)
>>> d['big3'] = numpy.arange(1000)
>>> # dump from memory cache to the on-disk archive
>>> d.dump()
>>> # clear the memory cache
>>> d.clear()
>>> d
dir_archive('stuff', {}, cached=True)
>>> # only load one entry to the cache from the archive
>>> d.load('big1')
>>> d['big1'][-3:]
array([997, 998, 999])
>>> 

klepto大量のストレージへの高速かつ柔軟なアクセスを提供します。アーカイブが並列アクセスを許可している場合 (たとえば、一部のデータベース)、結果を並列で読み取ることができます。また、異なる並列プロセスまたは異なるマシンで結果を共有することも簡単です。ここでは、同じディレクトリ アーカイブを指す 2 番目のアーカイブ インスタンスを作成します。2 つのオブジェクト間でキーを渡すのは簡単で、別のプロセスと同じように機能します。

>>> f = klepto.archives.dir_archive('stuff', cached=True, serialized=True)
>>> f
dir_archive('stuff', {}, cached=True)
>>> # add some small objects to the first cache  
>>> d['small1'] = lambda x:x**2
>>> d['small2'] = (1,2,3)
>>> # dump the objects to the archive
>>> d.dump()
>>> # load one of the small objects to the second cache
>>> f.load('small2')
>>> f       
dir_archive('stuff', {'small2': (1, 2, 3)}, cached=True)

また、さまざまなレベルのファイル圧縮から選択したり、ファイルをメモリ マップするかどうかを選択したりできます。ファイル バックエンドとデータベース バックエンドの両方に、さまざまなオプションがあります。ただし、インターフェイスは同じです。

ガベージ コレクションとディクショナリの一部の編集に関するその他の質問に関してはklepto、メモリ キャッシュからのオブジェクトのロードと削除、ダンプ、ロード、およびアーカイブ バックエンドとの同期、または他の辞書メソッド。

ここでより長いチュートリアルを参照してください: https://github.com/mmckerns/tlkklp

kleptoここにアクセスしてください: https://github.com/uqfoundation

于 2015-07-25T14:27:22.680 に答える
4

メモリ エラーが発生し、プロトコル = 2 を使用して解決しました。

cPickle.dump(obj, file, protocol=2)

于 2015-05-06T18:28:47.313 に答える
2

キーと値が文字列の場合、Python 標準ライブラリで利用可能な組み込みの永続的なキー値ストレージ エンジンの 1 つを使用できます。anydbmモジュール ドキュメントの例:

import anydbm

# Open database, creating it if necessary.
db = anydbm.open('cache', 'c')

# Record some values
db['www.python.org'] = 'Python Website'
db['www.cnn.com'] = 'Cable News Network'

# Loop through contents.  Other dictionary methods
# such as .keys(), .values() also work.
for k, v in db.iteritems():
    print k, '\t', v

# Storing a non-string key or value will raise an exception (most
# likely a TypeError).
db['www.yahoo.com'] = 4

# Close when done.
db.close()
于 2013-07-07T19:12:15.007 に答える
2

ストリーミング ピクルを使用してみました: https://code.google.com/p/streaming-pickle/

ストリーミングピクルに切り替えることで、同様のメモリエラーを解決しました。

于 2013-07-11T15:16:55.913 に答える
1

私は最近この問題を抱えていました。ASCII とバイナリ プロトコル 2 で cpickle を試したところ、20 GB 以上のデータでトレーニングされた sci-kit Learn の SVM が、メモリ エラーのためにピクルされていないことがわかりました。ただし、dill パッケージは問題を解決したようです。Dill はディクショナリに多くの改善をもたらすわけではありませんが、ストリーミングには役立つ可能性があります。これは、ピクルス化されたバイトをネットワーク経由でストリーミングするためのものです。

import dill

with open(path,'wb') as fp:
    dill.dump(outpath,fp)
    dill.load(fp)

効率が問題になる場合は、データベースへのロード/保存を試してください。この場合、ストレージ ソリューションが問題になる可能性があります。123 mb の Pandas は問題ないはずです。ただし、マシンのメモリが限られている場合、SQL はデータに対して高速で最適化されたバッグ操作を提供し、通常はマルチスレッドをサポートします。poly kernel svm が保存されました。

于 2015-07-24T18:58:53.907 に答える