2017-01-16 3 views
1

私は多数のデータファイルを持ち、データファイルからロードされた各データは何百回も再サンプリングされ、いくつかの方法で処理されます。これを行うにはnumpyを使用しました。私が直面しているのは、プログラムを数時間実行した後のメモリエラーです。それぞれのデータが別々に処理され、結果はのデータが格納されているので、以前のデータで使用されていたメモリを解放できると思いますのでdel variable_name + gc.collect()を使用しましたが、これは動作しません。その後、this postthis postに示唆されているように、multiprocessingモジュールを使用しましたが、まだ動作しません。ここでどのように効果的にPythonでメモリを解放するには?

は私のメインのコードです:

import scipy.io as scio 
import gc 
from multiprocessing import Pool 

def dataprocess_session: 
    i = -1 
    for f in file_lists: 
     i += 1 
     data = scio.loadmat(f) 
     ixs = data['rm_ix'] # resample indices 
     del data 
     gc.collect() 
     data = scio.loadmat('xd%d.mat'%i) # this is the data, and indices in "ixs" is used to resample subdata from this data 

     j = -1 
     mvs_ls_org = {} # preallocate results files as dictionaries, as required by scipy.savemat. 
     mvs_ls_norm = {} 
     mvs_ls_auto = {} 
     for ix in ixs: 
      j += 1 
      key = 'name%d'%j 
      X = resample_from_data(data,ix) 
      mvs_ls_org[key] = process(X) 

     scio.savemat('d%d_ls_org.mat'%i,mvs_ls_org) 
     del mvs_ls_org 
     gc.collect() 

     j = -1 
     for ix in ixs: 
      j += 1 
      key = 'name%d'%j 
      X = resample_from_data(data,ix) 
      X2 = scale(X.copy(), 'norm') 
      mvs_ls_norm[key] = process(X2) 

     scio.savemat('d%d_ls_norm.mat'%i,mvs_ls_norm) 
     del mvs_ls_norm 
     gc.collect() 

     j = -1 
     for ix in ixs: 
      j += 1 
      key = 'name%d'%j 
      X = resample_from_data(data,ix) 
      X2 = scale(X.copy(), 'auto') 
      mvs_ls_auto[key] = process(X2) 

     scio.savemat('d%d_ls_auto.mat'%i,mvs_ls_auto) 
     del mvs_ls_auto 
     gc.collect() 

     # use another method to process data 
     j = -1 
     mvs_fcm_org = {} # also preallocate variable for storing results 
     mvs_fcm_norm = {} 
     mvs_fcm_auto = {} 
     for ix in ixs: 
      j += 1 
      key = 'name%d'%j 
      X = resample_from_data(data['X'].copy(), ix) 
      dp, _ = process_2(X.copy()) 
      mvs_fcm_org[key] = dp 

     scio.savemat('d%d_fcm_org.mat'%i,mvs_fcm_org) 
     del mvs_fcm_org 
     gc.collect() 

     j = -1 
     for ix in ixs: 
      j += 1 
      key = 'name%d'%j 
      X = resample_from_data(data['X'].copy(), ix) 
      X2 = scale(X.copy(), 'norm') 
      dp, _ = process_2(X2.copy()) 
      mvs_fcm_norm[key] = dp 

     scio.savemat('d%d_fcm_norm.mat'%i,mvs_fcm_norm) 
     del mvs_fcm_norm 
     gc.collect() 

     j = -1 
     for ix in ixs: 
      j += 1 
      key = 'name%d'%j 
      X = resample_from_data(data['X'].copy(), ix) 
      X2 = scale(X.copy(), 'auto') 
      dp, _ = process_2(X2.copy()) 
      mvs_fcm_auto[key] = dp 

     scio.savemat('d%d_fcm_auto.mat'%i,mvs_fcm_auto) 
     del mvs_fcm_auto 
     gc.collect() 

これは私がやった最初の方法です。私のコンピュータは8つのCPUコアを持っているので、私はfile_listsを7つの部分に分割し、7つのpython画面を走らせました。 このようにしてもMATLABでは問題ありません。メモリエラーが発生する可能性があるので、ixs以上の繰り返しは組み合わせないので、resample_from_dataを実行し、結果を別々に保存しました。入力としてfile_lists内のファイル名で並列化file_lists以上の反復を実行した

pool = Pool(processes=7) 
pool.map(dataprocess_session_2, file_lists) 

:メモリエラーが解消されないように、私はとしてPoolクラスを使用していました。

すべてのコードはopenSuSEで実行され、python 2.7.5,8 cores CPUおよび32G RAMで実行されます。私は使用されたメモリを監視するためにtopを使用しました。すべての行列はそれほど大きくなく、すべてのコードを使用してロードされたデータのいずれかを実行すると問題ありません。しかし、file_listsを何度も繰り返しても、空きメモリは劇的に減少します。この現象はデータ自体に起因するものではないと私は確信しています。なぜなら、このような大きなメモリは、最大のデータ・マトリックスが処理中であっても使用されるべきではないからです。以前のデータを処理したり、処理結果を保存したりして使用したメモリを解放しようとした上記の方法では、実際にメモリが解放されていないと思われました。

提案がありますか?

+0

なぜ私はdownvotedされましたか? – Elkan

+0

私はこれを正しく自分自身で読む必要がありますが、私はあなたが 'gc'の手をこのように強制することはできないと思います。 Pythonは参照カウントを使ってオブジェクトを削除するかどうかを判断するので、 'gc.collect()'はおそらくそれらのオブジェクトを直ちに削除していません。これらのループのそれぞれを、データを返さない独自の関数に分解したい場合は、もっと希望があるかもしれませんが、もう一度Python gcで読むことを援助するだけです。その提案。うまくいけば、もっと精通した人が明らかにできることを望みます。 – roganjosh

+0

あなたの提案に更新してください:エラーは発生しませんが、この2日間はデータセットを実行した後、数KBのメモリ(PCの32G RAMと比較して)のみが空きました。処理されるデータのサイズが比較的小さいので、私がこの方法で使用すると、メモリがまだ使い果たされる可能性があります。 – Elkan

答えて

-3

これはいくつかの助け、gc.collect()を明示的に同時に自動的にループが終了すると解放されdel

+1

"以前のデータで使用されていたメモリを解放できると思いますので、del variable_name + gc.collect()を使用しましたが、これは機能しません。 – roganjosh

0

すべての変数であってもよいです。その後、私は彼らがあなたの問題だとは思わない。私はそれがあなたのマシンが単に(最悪の場合)7つのスレッドを同時に処理することができない可能性が高いと思う7は同時に実行data = scio.loadmat(f)。あなたは、その呼び出しをロック付きの重要なセクションとしてマークしようとすることができます。

+0

ありがとうございます。これについてもっと説明できますか?7つのデータが同時にメモリにロードされることは問題ではないので、「マシンは7つのスレッドを同時に処理できない7つのスレッド= scio.loadmat(f)」を処理できません。 – Elkan

+0

これは7つのデータだけではありません。すべてのスレッドが最大量のメモリを使用している最悪のケースについて考える必要があります。私はどのオブジェクトが最大のものかを教えてくれません。それらをプロファイルすることができます(シングルスレッドモードで最適です)。 –

+0

私は参照してください。私はMATLABを同じデータセットに使うのですが、Pythonコードの 'process'関数で指定された別の処理メソッドを使用しました。さらにMATLABのメモリにロードされ、何日も実行してもエラーはありません。私の行列はそれほど大きくなく、返された 'X'と' X2'は元の行列と同じ大きさであり、 'ixs'による反復の後でも大きな空き領域があります。これはlinuxの 'top'によって監視されます。私はpythonが 'del'の後でも' free lists'を保持していることに気付きましたが、私は効果的な解決策を見いだせませんでした。だから私は何かを逃したかどうかは疑問だ。 – Elkan

関連する問題