我一直在努力寻找使下面一段代码执行得更快的方法:
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上存储图表。这些图表稍后会动态呈现给用户。
有人请帮助我使用线程,以便我可以使用所有核心并使此功能更快地执行吗?或者指出改进它的想法?
答案 0 :(得分:3)
对于描述,使用多处理比使用线程要好得多......你有一个“令人尴尬的并行”问题,并且没有磁盘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秒。
希望有所帮助...
答案 1 :(得分:2)
当且仅当pylab在执行时释放gil时,线程将帮助您 此外,pylib必须是线程安全的,并且您的代码必须以线程安全的方式使用它,并且情况可能并非总是如此。
那就是说,如果你打算使用线程,我认为这是一个典型的作业队列案例;因此,我会使用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()