2011-01-11 36 views
13

大きなバッチジョブをより速く終了するために、いくつかのプロットを並行して実行しようとしています。この目的のために、私は作成を計画している各プロットのスレッドを開始します。Matplotlib:複数のスレッドで同時にプロットする

私は、各スレッドがプロットを終了して終了することを望んでいました(私が理解するように、Pythonはrun()内のすべてのステートメントを通過するときにスレッドを閉じます)。以下は、この動作を示すコードです。

図を作成する行がコメントアウトされている場合、期待どおりに実行されます。もう一つの役に立つ点は、あなたが1つのスレッドしか生成しないときに期待どおりに動くことです。

import matplotlib.pyplot as plt 
import time 
import Queue 
import threading 

def TapHistplots(): 
    ## for item in ['str1']: 
# # it behaves as expected if the line above is used instead of the one below 
    for item in ['str1','str2']: 
     otheritem = 1 
     TapHistQueue.put((item, otheritem)) 
     makeTapHist().start() 

class makeTapHist(threading.Thread): 
    def run(self): 
     item, otheritem = TapHistQueue.get() 
     fig = FigureQueue.get() 
     FigureQueue.put(fig+1) 
     print item+':'+str(fig)+'\n', 
     time.sleep(1.3) 
     plt.figure(fig) # comment out this line and it behaves as expected 
     plt.close(fig) 

TapHistQueue = Queue.Queue(0) 
FigureQueue = Queue.Queue(0) 
def main(): 
    start = time.time() 
    """Code in here runs only when this module is run directly""" 
    FigureQueue.put(1) 
    TapHistplots() 
    while threading.activeCount()>1: 
     time.sleep(1) 
     print 'waiting on %d threads\n' % (threading.activeCount()-1), 
    print '%ds elapsed' % (time.time()-start) 

if __name__ == '__main__': 
    main() 

助けを歓迎します。

+3

をあなたが実際にうまくいかない何を言っていませんでした、それはのように聞こえるが、何らかのスレッドの並行性の問題。 –

+0

私は実際に何がうまくいかないのか分かりません。私はエラーを出さず、Pythonのプロセスは実行し続けます。また、メインスレッドのprint文は1秒後に実行されますが、1秒後には実行されません。タスクマネージャーの一見は、プロセスが多くのCPUを使い続けていることを示しています。私は残念ながら、深刻なデバッグの経験が限られています。 – Boris

+0

'makeTapHist()。start()'を複数回呼び出すつもりですか?おそらくループの外側にあるように見えます。 –

答えて

4

pylabインターフェイスには、解決策があります。Asynchronous plotting with threadsです。

pylabがなければ、各マットプラットホームのバックエンド(Qt、GTK、WX、Tk)ごとに異なるソリューションが存在する可能性があります。問題は、各GUIツールキットにそれぞれ独自のGUIメインループがあることです。 ipythonはどのように扱われているのでしょうか。

+2

私が知る限り、提供されるリンクは、プロットを並行して作成する方法ではなく、多くのスレッドから1人の人物と作業する方法を示しています。 私が理解しているように、バックエンドはmatplotlibをインタラクティブに使うとき(ipythonのように)考慮する必要がありました。あなたがこの例にどのように当てはまるかを説明できるなら、私はそれを感謝します。 – Boris

+0

@Boris:バックエンドは問題ありません。たとえば、http://ideone.com/J42rnはデフォルトのバックエンドでセグメント化エラーを生成します。 – jfs

+2

btw、 'マルチプロセッシング' vesrionははるかに高速ですhttp://ideone.com/lFXOT – jfs

18

なぜマルチプロセッシングを使用しないのですか?あなたの説明からわかる限り、スレッディングはあまり助けになりません。

Matplotlibはすでにスレッド化されているため、一度に複数の図を表示して操作することができます。マルチコアマシンでバッチ処理を高速化したい場合は、マルチプロセッシングを必要としません。基本的な例として

警告:これは、あなたがそれを実行してどんなディレクトリ内の20個の小さな.PNGファイルを作成します!)

import multiprocessing 
import matplotlib.pyplot as plt 
import numpy as np 

def main(): 
    pool = multiprocessing.Pool() 
    num_figs = 20 
    input = zip(np.random.randint(10,1000,num_figs), 
       range(num_figs)) 
    pool.map(plot, input) 

def plot(args): 
    num, i = args 
    fig = plt.figure() 
    data = np.random.randn(num).cumsum() 
    plt.plot(data) 
    plt.title('Plot of a %i-element brownian noise sequence' % num) 
    fig.savefig('temp_fig_%02i.png' % i) 

main() 
+1

へのリンクを指摘しました。さらに、 'マルチプロセッシング 'バージョンは' threading'バージョンに比べて超高速です – jfs

関連する問題