Python 线程化以快速创建大量图表
我一直在试图找到让以下代码执行得更快的方法:Python 线程化以快速创建大量图表,python,multithreading,optimization,matplotlib,Python,Multithreading,Optimization,Matplotlib,我一直在试图找到让以下代码执行得更快的方法: 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] =
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命令,它们在这里只是为了说明)创建了一个字典(MYTAMDICT),我用cString对象填充了它,用于在memmory上存储图表。这些图表稍后会动态呈现给用户
有人能帮我利用线程,这样我就可以使用我所有的内核,使这个功能执行得更快吗?或者告诉我一些改进的想法?如果且仅当pylab在执行时释放gil时,线程将帮助您。
此外,pylib必须是线程安全的,并且您的代码必须以线程安全的方式使用它,而这种情况可能并不总是如此 也就是说,如果要使用线程,我认为这是作业队列的经典案例;因此,我会使用一个,足够好的来处理这个模式 这里有一个示例,我只是通过干预您的代码和队列文档中给出的示例而给出。我甚至没有彻底检查它,所以它会有bug;与其说是给出一个想法,不如说是给出一个想法
# "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()
根据描述,使用多处理比使用线程要好得多。。。您有一个“令人尴尬的并行”问题,并且没有磁盘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秒
希望这有点帮助……当前的性能是什么?它需要快多少?#史蒂文:如果我在for循环的开头插入一个“print I”,我可以看到每张图像需要将近1秒的时间。但是当我有了我应该使用的真正的pylab代码时,这个时间会增加。此函数将在用户每次更改新数据库时运行,因此它会经常更改。我知道我可以只画第一张图片,而另一张是在背景中完成的,但我觉得线程化听起来是最好的解决方案。这很酷。谢谢你的帮助。但我有个问题要问你。我为Python2.4安装了一个多处理的后端口,但是当我使用你的代码时,我得到了:***************************************************************************************************************************************加载-c*********************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************?IOError:[Errno 2]没有这样的文件或目录:'-c'**加载时间:0.00秒**警告:脚本中有错误,请按任意键退出?非常感谢你的帮助。@relima-Huh。。。我猜这是2.4上的多处理的问题。。。无论如何,在2.6和2.7上,一切似乎都很顺利。。。恐怕我没有比这更好的主意了,不过。。。