29

我正在尝试并行进行一些绘图以更快地完成大批量作业。为此,我为我计划制作的每个情节开始一个线程。

我曾希望每个线程都能完成其绘图并自行关闭(据我了解,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()

任何帮助都将受到应有的赞赏。

4

2 回答 2

31

为什么不只使用多处理?据我从您的描述中可以看出,无论如何,线程不会对您有太大帮助...

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()
于 2011-01-11T20:51:20.433 回答
6

对于pylab接口,有一个解决方案Asynchronous plotting with threads

如果没有pylab,每个 matplotlib 的后端(Qt、GTK、WX、Tk)可能会有不同的解决方案。问题是每个 GUI 工具包都有自己的 GUI 主循环。你可以看到如何ipython处理它。

于 2011-01-11T18:00:41.080 回答