【问题标题】:Python3 filling a dictionary concurrentlyPython3同时填充字典
【发布时间】:2016-02-22 20:17:11
【问题描述】:

我想循环填充字典。循环中的迭代相互独立。我想在具有数千个处理器的集群上执行此操作。这是我尝试和需要做的简化版本。

import multiprocessing

class Worker(multiprocessing.Process):
   def setName(self,name):
       self.name=name
   def run(self):
       print ('In %s' % self.name)
       return

if __name__ == '__main__':
   jobs = []
   names=dict()
   for i in range(10000):
       p = Worker()
       p.setName(str(i))
       names[str(i)]=i
       jobs.append(p)
       p.start()
   for j in jobs:
       j.join()

我在自己的电脑上用python3试过这个,收到如下错误:

    ..
    In 249
    Traceback (most recent call last):
      File "test.py", line 16, in <module>
        p.start()
      File         "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/multiprocessing/process.py", line 105, in start
    In 250
        self._popen = self._Popen(self)
      File         "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/multiprocessing/context.py", line 212, in _Popen
return _default_context.get_context().Process._Popen(process_obj)
      File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/multiprocessing/context.py", line 267, in _Popen
return Popen(process_obj)
      File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/multiprocessing/popen_fork.py", line 20, in __init__
self._launch(process_obj)
      File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/multiprocessing/popen_fork.py", line 66, in _launch
parent_r, child_w = os.pipe()
    OSError: [Errno 24] Too many open files

有没有更好的方法来做到这一点?

【问题讨论】:

    标签: python python-3.x python-multiprocessing


    【解决方案1】:

    multiprocessing 通过管道与其子进程对话。每个子进程需要两个打开的文件描述符,一个用于读取,一个用于写入。如果您启动 10000 个工作人员,您将结束打开 20000 个文件描述符,这超出了 OS X 的默认限制(您的路径表明您正在使用该限制)。

    您可以通过提高限制来解决此问题。有关详细信息,请参阅https://superuser.com/questions/433746/is-there-a-fix-for-the-too-many-open-files-in-system-error-on-os-x-10-7-1 - 基本上,它相当于设置两个 sysctl 旋钮并提高 shell 的 ulimit 设置。

    【讨论】:

    • 我不认为他在 OS X 上运行具有数千个处理器内核的系统。
    • 是的,但他正在尝试在 OS X 上创建 10000 个工作人员。
    【解决方案2】:

    您现在一次生成 10000 个进程。这真的不是个好主意。
    您看到的错误肯定是因为 multiprocessing 模块(似乎)使用管道进行 Inter Proccess C通信和开放管道/FD 有限制。

    我建议使用没有Global interpreter lock 的python 解释器,例如Jython 或IronPython,只需将multiprocessing 模块替换为threading 模块。


    如果您仍想使用multiprocessing 模块,您可以使用这样的进程池来收集返回值:
    from multiprocessing import Pool
    
    def worker(params):
        name, someArg = params
        print ('In %s' % name)
        # do something with someArg here
        return (name, someArg)
    
    if __name__ == '__main__':
        jobs = []
        names=dict()
        # Spawn 100 worker processes 
        pool = Pool(processes=100)
        # Fill with real data
        task_dict = dict(('name_{}'.format(i), i) for i in range(1000))
        # Process every task via our pool
        results = pool.map(worker, task_dict.items())
        # And convert the rsult to a dict
        results = dict(results)
        print (results)
    

    这也应该对threading 模块进行最小的更改。

    【讨论】:

      猜你喜欢
      • 2019-10-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-01-20
      • 1970-01-01
      • 1970-01-01
      • 2020-10-28
      相关资源
      最近更新 更多