为什么我的Python多处理工作进程不使用多个内核?

时间:2014-05-30 18:36:16

标签: windows python-3.x multiprocessing

使用来自多处理的Pool类,我将数据库搜索任务拆分为并行进程,每个进程都针对我已加载到内存中的非常大的数据库运行一组正则表达式。 该程序运行在一个非常强大的Windows服务器上,具有60多个内核和大量内存。

我的Python编程经验,特别是多处理,是非常表面的。

当我第一次创建程序时,一切工作都很好,每个工人都处理好它的作品并继续下一个。我没有触摸它几个月,直到我不得不对数据库查询进行一些格式化更改,但是当我再次启动它时它运行得太慢了。 在测试中,我确定我生成的进程数量并没有真正改变运行速度,实际上看着任务管理器显示了那里的所有进程,但其中只有一个实际上显示出任何工作迹象

def calc(ruleList,record):
    returnList = []
    print(record[5],end = '\r')
    hits = recordIterator(ruleList,record)
    for h in hits:
        returnList.append([record[0],record[1],h])
    return returnList

nthreads = 48
hname = 'Hits.txt'
p = multiprocessing.Pool(processes = nthreads)
Hits = []
for record in Records:
    Hits.append((p.apply_async(calc, (rules, record))).get())

hhandle = open(hname, "w")
for hit in Hits:
    try:
        for x in hit:
            hhandle.write(str(x[0])+'|'+str(x[1])+'|'+str(x[2])+'\n')
    except (UnicodeEncodeError,UnicodeDecodeError):
        pass
hhandle.close()

我不是机器的管理员,我不熟悉如何配置服务器,但在我看来,Windows根本就没有安排子进程来分离核心。 我尝试以多种不同的方式重新配置我的代码,以避免潜在的多处理阻塞,但每个功能变化最终都会遇到同样的问题。

我的代码中是否有某些内容让我错过了那些扼杀流程的内容? 是否有一些Windows Server设置可能已被更改为取消我的员工使用单独的核心资格?

2 个答案:

答案 0 :(得分:2)

在我看来,代码(p.apply_async(calc, (rules, record))).get()正在强制您的程序一次只运行一个作业。在启动下一个作业之前,父进程将在get()中等待上一个作业的结果可用。

尝试通过拨打Records来替换apply_async和多个starmap来电的循环:

Hits = p.starmap(calc, ((rules, record) for record in Records))

这会将记录传递给池,并且只有在它们全部被发送后才会阻止结果进入。

答案 1 :(得分:0)

要充实@ blckknght的答案:apply_async()提交作业,但.get()立即要求结果。一个更简单的解决方案是提交所有工作,然后在进入时获取每个结果,无论顺序如何。也就是说,使用imap_unordered()

import multiprocessing

def calc(num):
    return num*2

pool = multiprocessing.Pool(5)
for output in pool.imap_unordered(calc, [1,2,3]):
    print 'output:',output

输出

output: 2
output: 4
output: 6