Matplotlib: одновременное построение в несколько потоков - PullRequest
17 голосов
/ 11 января 2011

Я пытаюсь выполнять параллельное построение графиков, чтобы быстрее выполнять большие пакетные задания.С этой целью я запускаю поток для каждого графика, который планирую сделать.

Я надеялся, что каждый поток завершит свое построение и закроет себя (насколько я понимаю, Python закрывает потоки, когда они проходят через всеоператоры в run ()).Ниже приведен код, демонстрирующий это поведение.

Если строка, которая создает фигуру, закомментирована, она работает так, как ожидалось.Еще один правдоподобно полезный тидбит в том, что он также работает, как и ожидалось, когда вы порождаете только один поток.

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()

Любая помощь приветствуется.

Ответы [ 2 ]

24 голосов
/ 11 января 2011

Почему бы просто не использовать многопроцессорность? Насколько я могу судить по твоему описанию, многопоточность не сильно тебе поможет, во всяком случае ...

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()
5 голосов
/ 11 января 2011

Для интерфейса pylab есть решение Асинхронное построение с потоками .

Без pylab могут быть разные решения для каждого бэкенда matplotlib (Qt, GTK, WX, Tk).Проблема состоит в том, что каждый инструментарий GUI имеет каждый собственный mainloop GUI.Вы могли видеть, как ipython справляется с этим.

...