3

hereの提案に従って、次のコードで作成された ZODB を使用してデータを保存しました。

# structure of the data [around 3.5 GB on disk]
bTree_container = {key1:[ [2,.44,0], [1,.23,0], [4,.21,0] ...[10,000th element] ], key2:[ [3,.77,0], [1,.22,0], [6,.98,0] ..[10,000th element] ] ..10,000th key:[[5,.66,0], [2,.32,0], [8,.66,0] ..[10,000th element]]}

# Code used to build the above mentioned data set
for Gnodes in G.nodes():      # Gnodes iterates over 10000 values 
Gvalue = someoperation(Gnodes)
    for i,Hnodes in enumerate(H.nodes()):  # Hnodes iterates over 10000 values 
        Hvalue =someoperation(Hnodes)
        score = SomeOperation on (Gvalue,Hvalue)
        btree_container.setdefault(Gnodes, PersistentList()).append([Hnodes, score, 0]) # build a list corresponding to every value of Gnode (key)
        if i%5000 == 0       # save the data temporarily to disk.
           transaction.savepoint(True)
transaction.commit()         # Flush all the data to disk

今、私は(別のモジュールで)(1)保存されたデータを変更し、(2)それを並べ替えたいと思っています。以下は私が使用していたコードです:

storage = FileStorage('Data.fs')
db = DB(storage)
connection = db.open()
root = connection.root()
sim_sorted = root[0]

# substitute the last element in every list of every key (indicated by 0 above) by 1
# This code exhausts all the memory, never get to the 2nd part i.e. the sorting 
for x in sim_sorted.iterkeys():
    for i,y in enumerate(sim_sorted[x]):
        y[3] = 1
        if i%5000 ==0
            transaction.savepoint()

# Sort all the lists associated with every key in he reverse order using middle element as key   
[sim_sorted[keys].sort(key = lambda x:(-x[1])) for keys in sim_sorted.iterkeys()]

ただし、値を編集するために使用されるコードは、すべてのメモリを使い果たしています (決して並べ替えを行うことはありません)。これがどのように機能するかはわかりませんが、コードに何かひどく問題があり、ZODB がすべてをメモリに取り込んでいるため、問題が発生しているように感じます。メモリの問題に遭遇することなく、ZODB に格納された要素の置換と並べ替えなど、望ましい効果を達成するための正しい方法は何でしょうか? また、コードは非常に遅いです。それを速くするための提案はありますか?

[注: これらの変更をデータベースに書き戻す必要はありません]

connection.cacheMinimize()編集内部ループの後にコマンドを追加することでメモリ使用量が少し改善されたようですが、しばらくすると RAM 全体が消費され、困惑しています。

4

1 に答える 1

1

あなたの記憶を殺しているのは並べ替えではないと確信していますか?

各 PersistentList がメモリに収まる必要があることに注意してください。これは 1 つの永続的なレコードであるため、アクセス時に全体としてロードされます。

このように実行するようにコードを変更して、何が起こるかを確認します。

for x in sim_sorted.iterkeys():
    for y in sim_sorted[x]:
        y[3] = 1
    sim_sorted[x].sort(key=lambda y: -y[1])
    transaction.savepoint()

ここで、リスト全体を一度に処理して並べ替えます。結局のところ、それはすでに 1 つのメモリにロードされています。処理後、ZODB にこの段階が終了したことを伝え、変更されたリスト全体が一時ストレージにフラッシュされます。半分しか終わっていない場合は、フラッシュしてもほとんど意味がありません。

これでもメモリに収まらない場合は、データ構造を再考し、大きなリストを小さな永続レコードに分割して、全体を 1 つにロードすることなく一度にチャンクで作業できるようにする必要があります。

于 2012-07-05T06:48:36.417 に答える