python多处理can';找不到错误

python多处理can';找不到错误,python,process,multiprocessing,Python,Process,Multiprocessing,我正在尝试运行具有多处理功能的函数。代码如下: import multiprocessing as mu output = [] def f(x): output.append(x*x) jobs = [] np = mu.cpu_count() for n in range(np*500): p = mu.Process(target=f, args=(n,)) jobs.append(p) running = [] for i in range(np):

我正在尝试运行具有多处理功能的函数。代码如下:

import multiprocessing as mu

output = []
def f(x):
    output.append(x*x)


jobs = []
np = mu.cpu_count()

for n in range(np*500):
    p = mu.Process(target=f, args=(n,))
    jobs.append(p)


running = []

for i in range(np):
    p = jobs.pop()
    running.append(p)
    p.start()

while jobs != []:
    for r in running:
        if r.exitcode == 0:
            try:
                running.remove(r)
                p = jobs.pop()
                p.start()
                running.append(p)
            except IndexError:
                break

print "Done:"
print output
输出为[],但应为[1,4,9,…]。有人看到我哪里出错了吗?

编辑: 感谢@Roland Smith指出。 主要问题是函数
f(x)
。当子进程调用此函数时,它们无法细化
输出
变量(因为它不是共享的)

编辑: 正如@cdarke所说,在多处理中,您必须小心地控制子进程可以访问的共享对象(可能是一个锁),这是非常复杂和难以调试的

我个人建议使用
Pool.map
方法进行此操作

例如,我假设您直接运行此代码,而不是作为模块运行,那么您的代码将是:

import multiprocessing as mu

def f(x):
    return x*x

if __name__ == '__main__':   
    np = mu.cpu_count()
    args = [n for n in range(np*500)]

    pool = mu.Pool(processes=np)
    result = pool.map(f, args)
    pool.close()
    pool.join()
    print result
但有些事你必须知道

  • 如果只运行此文件而不使用模块导入,则
    if\uuuu name\uuu='\uu main\uuu':
    非常重要,因为python会将此文件作为其他进程的模块加载,如果不将函数“f”放在
    之外,如果uu name\uuu='\uuu main\uu':
    ,子进程将无法找到函数“f” **编辑:**谢谢@Roland Smith指出我们可以使用元组
  • 例如,如果函数f有多个参数,那么可能需要一个元组来实现

    def f((x,y)) return x*y args = [(n,1) for n in range(np*500)] result = pool.map(f, args) 定义f((x,y)) 返回x*y args=[(n,1)表示范围内的n(np*500)] 结果=pool.map(f,args) 或者查看更详细的讨论


  • 您使用的是
    多处理
    ,而不是
    线程
    。因此,您的
    输出
    列表不会在进程之间共享

    有几种可能的解决办法

  • 保留大部分程序,但使用
    多处理.Queue
    而不是列表。让工作人员将结果放入队列中,并从主程序读取结果。它会将数据从一个进程复制到另一个进程,因此对于大数据块来说,这将有很大的开销
  • 您可以以
    多处理.Array
    的形式使用共享内存。如果处理的数据很大,这可能是最好的解决方案
  • 使用
    。这将为您提供所有流程管理。就像队列一样,它将数据从一个进程复制到另一个进程。它可能是最容易使用的。在我看来,如果发送给每个工人/从每个工人发送的数据很小,这是最好的选择
  • 使用
    线程化
    ,以便线程之间共享
    输出
    列表。CPython中的线程限制一次只能有一个线程执行Python字节码,因此您可能无法获得预期的性能优势。与多处理解决方案不同,它不会利用多核

  • 粗略地看一下代码,您在哪里等待作业完成<代码>作业。join()在什么地方?似乎也缺少锁,但我还没有弄清楚您的逻辑think@cdarke什么<代码>无!=0相同的输出:S。如果我改为join(),则某些进程将完成,但父进程在调用进程join()之前不会注意到,不是吗?您的问题比共享列表的问题更大。关于2,您可以将所有参数放在一个
    元组中。
    。是的,您是对的,我与需要lamdba函数的其他方法混淆了,我将对此进行编辑。使用多处理,问题代码中的
    输出
    列表不共享。诚然,主要问题是
    def(x):output.append(x*x)
    ,当子进程调用此函数时,它们无法对
    输出
    变量进行微调(因为它不是共享的),我还将添加此函数,谢谢你的指点。