Matplotlib: одновременное построение в несколько потоков
Я пытаюсь сделать несколько параллельных заговоров, чтобы быстрее завершить работу с большими пакетами. С этой целью я запускаю тему для каждого сюжета, который планирую сделать.
Я надеялся, что каждый поток завершит свое построение и закроет себя (насколько я понимаю, 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 ответа
Почему бы просто не использовать многопроцессорность? Насколько я могу судить по твоему описанию, многопоточность мало тебе поможет, во всяком случае...
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()
За pylab
В интерфейсе есть решение Асинхронное построение с потоками.
Без pylab
для каждого бэкэнда matplotlib могут быть разные решения (Qt, GTK, WX, Tk). Проблема состоит в том, что каждый инструментарий GUI имеет каждый собственный mainloop GUI. Вы могли видеть, как ipython
имеет дело с этим.