线程化可以快速创建大量图表

2024-05-29 03:42:00 发布

您现在位置:Python中文网/ 问答频道 /正文

我一直在设法使以下代码执行得更快:

def do_chart(target="IMG_BACK", xlabel="xlabel", ylabel="ylabel", title="title",       ydata=pylab.arange(1961, 2031, 1)):
    global MYRAMDICT
    MYRAMDICT = {}
    print "here"
    for i in range(70):
        MYRAMDICT[i] = cStringIO.StringIO()
        xdata = pylab.arange(1961, 2031, 1)
        pylab.figure(num=None, figsize=(10.24, 5.12), dpi=1, facecolor='w', edgecolor='k')
        pylab.plot(xdata, ydata, linewidth=3.0)
        pylab.xlabel(xlabel); pylab.ylabel(ylabel); pylab.title(i)
        pylab.grid(True)
        pylab.savefig(MYRAMDICT[i], format='png')
        pylab.close()

这个函数(请忽略pylab命令,它们只是为了说明)创建了一个dictionary(MYTAMDICT),我用cString对象填充它,这些对象用于在内存中存储图表。这些图表稍后会动态地呈现给用户。在

有人能帮我利用线程,这样我就可以使用我所有的核心,并使这个功能执行得更快吗?或者给我指点改进的方法?在


Tags: 对象titledefchart图表do代码执行pylab
2条回答

对于描述,您最好使用多处理而不是线程。。。您有一个“令人尴尬的并行”问题,而且没有磁盘IO约束(您正在写入内存),当然,在进程之间来回传递大型数据将非常昂贵,但是返回一个表示.png的字符串应该不会太糟糕。。在

可以很简单地完成:

import multiprocessing
import cStringIO

import matplotlib.pyplot as plt
import numpy as np

import itertools

def main():
    """Generates 1000 random plots and saves them as .png's in RAM"""
    pool = multiprocessing.Pool()
    same_title = itertools.repeat('Plot %i')
    fig_files = pool.map(plot, itertools.izip(xrange(1000), same_title))

def plot(args):
    """Make a random plot"""
    # Unfortunately, pool.map (and imap) only support a single argument to
    # the function, so you'll have to unpack a tuple of arguments...
    i, titlestring = args

    outfile = cStringIO.StringIO()

    x = np.cumsum(np.random.random(100) - 0.5)

    fig = plt.figure()
    plt.plot(x)
    fig.savefig(outfile, format='png', bbox_inches='tight')
    plt.title(titlestring % i)
    plt.close()

    # cStringIO files aren't pickelable, so we'll return the string instead...
    outfile.seek(0)
    return outfile.read()

main()

如果不使用多处理,在我的机器上需要大约250秒。对于多处理(8核),需要大约40秒。在

希望这有点帮助。。。在

当且仅当pylab在执行时释放gil时,线程将帮助您。
而且,在这种情况下,线程必须是安全的。在

也就是说,如果您要使用线程,我认为这是作业队列的一个经典案例;因此,我将使用一个queue object,它足以处理这个模式。在

这里有一个例子,我只是通过修改代码和队列文档中给出的示例来实现的。我甚至没有彻底检查它,所以它会有错误;它比任何东西都更能给出一个想法。在

# "Business" code
def do_chart(target="IMG_BACK", xlabel="xlabel", ylabel="ylabel", title="title",       ydata=pylab.arange(1961, 2031, 1)):
    global MYRAMDICT
    MYRAMDICT = {}
    print "here"
    for i in range(70):
      q.put(i)
    q.join()       # block until all tasks are done

def do_work(i):
    MYRAMDICT[i] = cStringIO.StringIO()
    xdata = pylab.arange(1961, 2031, 1)
    pylab.figure(num=None, figsize=(10.24, 5.12), dpi=1, facecolor='w', edgecolor='k')
    pylab.plot(xdata, ydata, linewidth=3.0)
    pylab.xlabel(xlabel); pylab.ylabel(ylabel); pylab.title(i)
    pylab.grid(True)
    pylab.savefig(MYRAMDICT[i], format='png')
    pylab.close()


# Handling the queue
def worker():
    while True:
        i = q.get()
        do_work(i)
        q.task_done()

q = Queue()
for i in range(num_worker_threads):
     t = Thread(target=worker)
     t.daemon = True
     t.start()

相关问题 更多 >

    热门问题