2017-12-21 8 views
1

Pythonのマルチプロセッシングモジュールを使用して実行しているコードが、警告またはエラーなしでハングします。私はプロットが生成されるときにそれを絞り込んだと思う。マルチプロセッシングとmatplotlibの間にいくつかの非互換性がありますか?プロット中にPythonマルチプロセッシングがハングアップする

私は、(numpy、scipy、pandasを使用して)Pythonで多数のデータセットを前処理しています。各データセットは、別々のデータファイルの集まりで構成されています。私は生データを読み込み、1つの.pklファイルと各データセットの.pngファイルを書きます。プロットは、matplotlibとseabornを使用して生成されます。図は表示されずにファイルに保存されます。各データセットの前処理は、互いに完全に独立している必要があります。

処理は連続して動作します。 preprocess.main_debugは()パス/ファイル名/ flagsにとると、ステータス文字列を返します( '完全'、 'スキップ' など):

import preprocess 

# Serial processing 
dataroot = '/Volumes/ExtData/' 
study = 'study0' 
datasets = ['data0', 'data1', 'data2'] 
force_preprocess = True 
quiet_console = False 

status = [preprocess.main_debug(dataroot, study, dataset, 
           force_preprocess, quiet_console) 
      for dataset in datasets] 

# Print summary 
print('\n---- Summary --------------') 
for d, s in zip(datasets, status): 
    print(' {}:\t{}'.format(d, s)) 

しかし、マルチプロセッシングがハング:

import multiprocessing as mp 
import logging 
import preprocess 

dataroot = '/Volumes/ExtData/' 
study = 'study0' 
datasets = ['data0', 'data1', 'data2'] 
force_preprocess = True 
quiet_console = True # Suppress console output 

# Send multiprocessing logs to console 
mp.log_to_stderr() 
logger = mp.get_logger() 
logger.setLevel(logging.INFO) 

# Parallel process 
pool = mp.Pool(processes=3, maxtasksperchild=1) 
results = [pool.apply_async(preprocess.main_debug, 
          args=(dataroot, study, dataset, 
          force_preprocess, quiet_console)) 
      for dataset in datasets] 
status = [p.get(timeout=None) for p in results] 

# Print summary 
print('\n---- Summary --------------') 
for d, s in zip(datasets, status): 
    print(' {}:\t{}'.format(d, s)) 

を私は」プロセスの数、maxtasksperchild、およびタイムアウトに影響を及ぼさずに動き回りました。私はロギングとマルチプロセッシングの間に互換性がないかもしれないことを示すいくつかのリンクをオンラインで見つけたので、すべてのロギングコードを削除しましたが、同じ方法で実行がハングアップします。

マルチプロセッシングバージョンのコードを実行すると、コンソールに表示されます。

$ python batchpreprocess.py 
[INFO/PoolWorker-1] child process calling self.run() 
[INFO/PoolWorker-2] child process calling self.run() 
[INFO/PoolWorker-3] child process calling self.run() 

7分後にCPU使用率が100%から0%に低下し、メモリ使用量が〜12GBから〜3MBに減少します。 3つの子プロセスが開始されていることがわかります。ものは、この状態で(最低でも、少なくとも)スタックされています。私は3つのデータセットでしかテストしていないので、私には不思議そうです。だから、3つの子プロセスしかないと思っていました。

$ python batchpreprocess.py 
[INFO/PoolWorker-1] child process calling self.run() 
[INFO/PoolWorker-2] child process calling self.run() 
[INFO/PoolWorker-3] child process calling self.run() 
[INFO/PoolWorker-4] child process calling self.run() 
[INFO/PoolWorker-5] child process calling self.run() 
[INFO/PoolWorker-6] child process calling self.run() 

ロギングステートメントでコードを振りかざしました。私は波形のプロットを生成するコードをプロットしているところでクラッシュします。プロットコードを削除すると、実行はそのポイントまで続きますが、次のプロットで停止します。

def main_debug(dataroot, study, dataset, force_preprocess, quiet_console): 
    try: 
     status = main(dataroot, study, dataset, 
         force_preprocess, quiet_console) 
     return status 
    except: 
     print('Problem in dataset {}'.format(dataset)) 
     return 'Exception' 

def main(dataroot, study, dataset, force_preprocess, quiet_console): 
    ... 
    [load files, do signal processing, make plots, save .pkl file] 
    ... 
    return 'Done' 

私は前処理の一環として作られたプロットを持っている必要があります:

preprocess.main_debugの内容は、()のようになります。 (保存されたpklファイルからのプロットは可能ですが、コードの大部分を再実行する必要があります)。他の誰かが似たようなものを実行し、回避策を知っていることを期待しています。

おかげで、

デレク

のPython 2.7、OSXハイシエラは、ちょうどアナコンダを使用してすべての私のパッケージを更新しました。

+0

私はmatplotlibのが今まで私が作るしようとしていたグラフを終えていないとの問題がありました。ちょうどあまりにも多くのデータポイントがあったことが判明し、それはそれにぶら下がっていました。データセットを切り捨てて、その小さな部分だけをグラフ化して、これが起こっている可能性があるかどうかを確認する必要があります。 –

+0

プロットコードが表示されません。あなたはそれがぶら下がっている場所だと確信していますか?どのバックエンドを使用していますか? AGGでない場合は、AGG –

+0

を試してみてください。何とかデッドロックに陥っているようです。これは、プロセスがリソースを共有し、通常マルチスレッドよりも起こりにくいマルチプロセッシングでのみ発生します。私があなたの投稿に見るものから、マルチプロセッシングの設定にはすべて正しいようです。 'preprocess.main_debug'のコードを追加できますか?または少なくともパラメータと関数の変数の初期設定? – hansaplast

答えて

1

matplotlibを設定して対話型バックエンドを使用すると、プロットはメインループを閉じるために閉じる必要のあるウィンドウを作成します。

これを避けるには、「agg」などの非インタラクティブバックエンドを使用します。

matplotlibrcファイルでパラメータを設定できます。

次のことが可能また、pyplotをインポートする、あなたが行うことができます:

import matplotlib 
matplotlib.use('agg') 
+0

ありがとう、ポール。スクリプトでshow()を呼び出すことはありませんでしたので、ウィンドウがポップアップすることは期待していませんでした。しかし、私はmacosxが異常であることについてのドキュメンテーションで何かを見ました。 "OSXウィンドウでのココアレンダリング(現在、matplotlibが非インタラクティブモードの場合、show()の動作がブロックされません)"多分それは関連しているでしょう。助けてくれてありがとう。 – dereky

関連する問題