Python多进程锁问题

6
我希望使用Python的多进程模块将字典列表相加。
以下是我的简化代码:
#!/usr/bin/python2.7
# -*- coding: utf-8 -*-

import multiprocessing
import functools
import time

def merge(lock, d1, d2):
    time.sleep(5) # some time consuming stuffs
    with lock:
        for key in d2.keys():
            if d1.has_key(key):
                d1[key] += d2[key]
            else:
                d1[key] = d2[key]

l = [{ x % 10 : x } for x in range(10000)]
lock = multiprocessing.Lock()
d = multiprocessing.Manager().dict()

partial_merge = functools.partial(merge, d1 = d, lock = lock)

pool_size = multiprocessing.cpu_count()
pool = multiprocessing.Pool(processes = pool_size)
pool.map(partial_merge, l)
pool.close()
pool.join()

print d
  1. 运行此脚本时,我遇到了这个错误。我该如何解决?

    RuntimeError: Lock objects should only be shared between processes through inheritance

  2. 在这种情况下,在merge函数中是否需要lock,或者Python会自动处理它?

  3. 我认为map应该做的是将一个列表中的内容映射到另一个列表中,而不是将所有内容都倒入单个对象中。所以有没有更优雅的方法来完成这样的事情?

1个回答

12
以下内容应该可以跨平台(也就是在Windows上运行),并且在Python 2和3中都能正常运行。它使用进程池初始化器将管理器字典设置为每个子进程中的全局变量。
FYI:
- 使用锁对于管理器字典是不必要的。 - 进程池中的进程数默认为CPU数量。 - 如果您不关心结果,可以使用apply_async而不是map
import multiprocessing
import time

def merge(d2):
    time.sleep(1) # some time consuming stuffs
    for key in d2.keys():
        if key in d1:
            d1[key] += d2[key]
        else:
            d1[key] = d2[key]

def init(d):
    global d1
    d1 = d

if __name__ == '__main__':

    d1 = multiprocessing.Manager().dict()
    pool = multiprocessing.Pool(initializer=init, initargs=(d1, ))

    l = [{ x % 5 : x } for x in range(10)]

    for item in l:
        pool.apply_async(merge, (item,))

    pool.close()
    pool.join()

    print(l)
    print(d1)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接