0

私のオブジェクトは、内部に約 100 万個のオブジェクトを含む辞書です ({} with {}、場合によっては {{}、{{}}、{}...}

FOR ループを使用して項目を実行しているときに、次の行でエラーが発生します。

lines = fp.readlines()
MemoryError: Fatal Python error: PyEval_RestoreThread: NULL tstate

このオブジェクトに対して実行するアクションは約 5 ~ 6 個あります。すべてを 1 つの反復ループで実行しようとすると、このエラーが発生します。分離されたループで実行 (各ループは 1 つのアクションを実行) - 最初の 2 つのループはうまく機能しますが、3 回目には常にループを実行しています (約 80,000 回の反復後) Python がクラッシュします (上記のメモリ エラー)。

アクションの順序を変更しました-つまり、ループの順序が変更されました.3番目の「for」ループで常に失敗します...

より強力で高速なマシンを使用してみましたが、それでもこれらのエラーが発生します。

お知らせ下さい。

PS

4

3 に答える 3

3

RAMには多すぎると思います。可能であれば、1 つの for ループでアクションを実行し、メモリ効率のために反復を最適化する必要があります。

fp.readlines()

ええと、それはファイルのすべての行を一度に読み取るため、その内容はすべてメモリにあります。ファイルの内容を辞書に変換する方法の詳細についてはわかりません。ただし、ファイル内の行に依存している場合は、反復ステップごとに新しい行を生成するファイルを単純に反復することができます。

for line in fp:
    # ...

ただし、ファイルのすべての情報を再び辞書に保存すると、同じ問題に再び直面することになります。

(可能であれば) 重複をチェックしてメモリに保存したデータを最適化すると、CPU が集中的に使用されますが、メモリ使用量を下げる必要がある場合があります。


コンシステント ストレージとジェネレーターの違いは、これら 2 つのスニペットが同じ操作を実行した後に明らかになるはずですが、前者は後者よりもメモリを集中的に使用します。iterate_toは関数を正確に複製したrange/xrangeものであり、単に実証的な目的を果たしていることに注意してください。

def iterate_to(num):
    list_ = []
    for i in xrange(num):
        list_.append(i)
    return list_

def operate_on(num):
    list_ = []
    for i in iterate_to(num):
        x = (i ** i + 5) / (i * 2)
        list_.append(x)
    return list_

print sum(operate_on(1000000))

関数はsumによって返されるリストの各要素を合計しoperate_onますが、それぞれ1000000 エントリ(!!) を持つ 2 つのリストはメモリ内で一貫しています。メモリ効率をもう少し向上させることができるとすでに考えているかもしれません。

def iterate_to(num):
    for i in xrange(num):
        yield i

def operate_on(num):
    for i in iterate_to(num):
        x = (i ** i + 5) / (i * 2)
        yield x

print sum(operate_on(1000000))

この例では、と関数のyield両方をジェネレーター関数にするために式が使用されています。反復中、各反復ステップで、反復の次の要素は、以前に構築されたアイテムのコレクションに依存するのではなく、直接計算されます。 ジェネレーターの詳細については、こちらをご覧ください。iterate_tooperate_on

于 2012-10-24T06:59:36.507 に答える
2

これはメモリの問題である可能性が最も高く、python 2.* は 2Gb を超える RAM を使用できません。これは、ガベージ コレクションの遅延が原因で発生する可能性があります。gc ライブラリをインストールし、集中的な処理ブロックの後 (各 FOR ループの後など) にガベージ コレクションを手動で呼び出してみてください。ディクショナリにファイルの内容を入力した後、ファイル オブジェクトからメモリをクリアします。とにかく、トップコマンドまたはタスクマネージャーでメモリ消費を調べることから始めます。

于 2012-10-24T07:28:44.287 に答える
0

gc.colletc() は私の問題を解決しませんでした。メモリ使用量の削減を引き起こした変更は、1 つの巨大な {Dictionary} 内の 1M オブジェクトを処理し、それらの一部を特別な [Lists] オブジェクトに「移動」することでした。メモリ。使用率は依然として非常に高い (約 1.7 GB) ですが、現在スクリプトは機能しており、クラッシュすることはありません。回答ありがとうございます。これらの回答から学び、非常に役に立ちました。

于 2012-10-25T12:39:11.363 に答える