2012-01-08 21 views
3

私は、Pythonスクリプトで12個のXMLファイル(30〜80メガバイトごと)をロードしています:)(でも、終了後にmultiprocessing.Poolとメモリリーク

import xml.etree.ElementTree as ET 
files = ['1.xml', '2.xml', ..., '11.xml', '12.xml'] 
trees = [ET.parse(f) for f in files] 

これを実行するために約50秒かかります。私はマルチプロセッシングとそれをスピードアップしようと思ったので、私はそれを数回実行していることでしょう:

import multiprocessing  
trees = [None] * len(files) 

def _parse_(i): 
    return (i, ET.parse(files[i])) 

def _save_((i, tree)): 
    trees[i] = tree 

def concurrent_parse(): 
    pool = multiprocessing.Pool() 
    for i in range(len(files)): 
     pool.apply_async(func=_parse_, args=(i,), callback=_save_) 
    pool.close() 
    pool.join() 

これが今の素敵な改良された、30代で実行されます。しかし、私はシェルからこれらのすべてを実行して、データを対話的に処理しています。最初の非並行バージョンが完成した後、Pythonのメモリ使用量は約1.73GBとなりました。同時実行後、メモリ使用量は2.57GBです。

私はマルチプロセッシングを初めて使用していますので、何か基本的なものを見逃してしまった場合は、私を許してください。しかし、プールを使用した後にメモリを失うというその他の問題は、私がやっているclose()を呼び出すことができないことを指しています。

PS - これが12のXMLファイルを読み込むための本当にダムな方法であれば、どうか言ってください。

+1

私はその問題が 'マルチプロセッシング 'に関するもので、私には興味があります(アップフォートし、購読しています)。可能ならば 'lxml.etree'の使用を検討してください。私は、それぞれ20 MBのテストファイルを生成しました。テスト結果 'lxml/xml'(マルチプロセッシングなし):time - 1.47/27.95 sec;メモリ - 411/640 MB。 – reclosedev

答えて

2

これは実際にはリークではないと思いますが、並列実装ではすべてのファイルを同時に保持するためにさらに多くのメモリが必要になります。その後、Pythonはオブジェクトを削除しているかもしれませんが、メモリをOSに返さないことがあります。これはPythonが既存のオブジェクトに必要なメモリよりも多くのメモリを使用するように見えます。
したがって、concurrent_parse()を何度も実行するとどうなりますか?メモリ使用量が一定であれば、漏れではありません。各実行の後にメモリが上がった場合、それは問題であり、リークを追跡するための情報についてはこのスレッドを参照してください。Python memory leaks

+0

これは魅力的な説明ですが、ファイルが別々のPythonプロセスによって同時に保持されるので、私は完全には確信していません。したがって、解析に使用するメモリをOSに返す必要があります。 メモリを最大にしてすべてのページングを開始するので、concurrent_parse()を再実行するとマシンが停止します(約10分を与えました)。私はそれを再実行したが、2-4ファイルしかない場合、メモリは約2GBで安定しているように見えます。しかし、4-6ファイルで再実行するとうまく動作し、他の時間がメモリの制限にぶつかることがあります。 いずれにせよ、 'マルチプロセッシング'は私が望んでいた魔法の弾丸ではないかもしれません! –

+0

'trees 'をすべてNoneにリセットしましたか?子プロセスがメインプロセスからオブジェクトのコピーを取得するので、これは重要です。ツリーにプロセスの数を掛け合わせた多くのデータがある場合は、このようにしてください。少しの実験の後、ツリーが実行間でリセットされている限り、concurrent_parse()を繰り返し実行した後にメモリが増えないように見えます(少なくともCentOS 5のPython 2.7では)。マルチプロセスを使用しているときのメモリ使用量の増加は、IPCのシリアル化によるものだと思います。 – user1013341

+0

うーん、私はあなたが意味するものを参照してください。私はあなたがおそらくメモリリークではないという点であなたの答えが正しいと思います。しかし、私は、元のプロセスが、すべてのインスタンスのコピーが異なるプロセスにある場合に700MBのメモリを追加してしまう理由について完全には満足していません。いずれにしても、Pythonのガベージ・システムは問題の範囲を超えているので、私はそれを休んでいます。ありがとう! –

関連する問題