我编写了一些Python代码,用于从大型数据库中提取信息,对数据库中的每个项目执行一些最大似然建模,然后存储结果。代码可以串行工作,每个项目需要1-2秒。问题是,我在数据库中有几百万个项目,因此代码的连续运行将花费数周时间。我可以访问一个拥有16个cpu的群集,并且我已经编写了一个功能,可以将初始输入目录分成"块,"在每个块上运行建模代码,然后组织结果。由于代码建模部分的复杂性及其对第三方python软件的依赖,我一直在尝试使用多处理来并行化这些代码,以便输入目录的每个块都在一个单独的cpu上运行。目前,我尝试产生的进程只能在一个cpu上运行。有谁知道如何解决这一问题?我是一名自学成才的科学程序员,所以我有一些使用Python的经验,尽管这是我第一次尝试并行化。代码太长了,不能完整地显示在这里,但它基本上做了以下几点:
def split(a, n):
k, m = len(a) / n, len(a) % n
return (a[i * k + min(i, m):(i + 1) * k + min(i + 1, m)] for i in xrange(n))
ncpus = mp.cpu_count()
chunks = list(split(catlist, ncpus))
images = [im1, im2, im3, im4, im5, im6, im7, im8, im9, im10, im11, im12]
def process_chunks(chunk):
database_chunk = database[chunk[:]]
for i in range(0,len(database_chunk)):
# perform some analysis
for j in range(0,len(images)):
# perform more analysis
my_dict = {'out1': out1, 'out2':out2, 'out3': out3}
return my_dict
pool = mp.Pool(processes=ncpus)
result = [pool.apply(process_chunks, args=(chunks[id],)) for id in range(0,len(chunks))]
对于数据库中只有13个项目的简单测试示例,这就是块的样子(大致均匀分割列表的列表):
chunks = [[0,1,2,3],[4,5,6],[7,8,9],[10,11,12]]
代码运行正常,pool.apply命令生成多个进程,但所有进程都在单个cpu上运行,并且运行时没有串行改进(实际上它有点慢,我想到期了)生成每个进程的开销)。有没有办法强制将每个进程分配给一个单独的cpu,所以当我将它应用于完整数据库(有数百万项)时,我得到了一些改进?或者也许是更好的解决这个问题的方法吗?
提前非常感谢!
注意:如果它进一步澄清情况,我是一名天文学家,数据库是一个包含超过一百万条目的大型源目录,图像是12个不同波段的宽场马赛克,而我是&#39 ; m对每个源的每个波段进行最大似然测光。
答案 0 :(得分:0)
我一开始以为你遇到了全局解释器锁,但是你已经使用multiprocessing
躲过了。值得庆幸的是,这意味着事情要比其他方面容易得多。来自the docs:
apply()内置函数的等效项。 阻塞直到结果准备好,因此apply_async()更适合并行执行工作。
(强调我的)
apply_async()
的API与apply()
略有不同,但这是一个非常简单的修改:
calculations = []
def reaper(result):
calculations.append(result)
for id in range(0, len(chunks)):
pool.apply_async(process_chunks, args=(chunks[id],), callback=reaper)