2016-02-22 2 views
3

Я хочу заполнить словарь в цикле. Итерации в цикле независимы друг от друга. Я хочу выполнить это на кластере с тысячами процессоров. Вот упрощенная версия того, что я пробовал и должен делать.Python3, заполняющий словарь одновременно

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 

Есть ли лучший способ сделать это?

ответ

1

В настоящий момент вы создаете 10000 процессов одновременно. Это действительно это не очень хорошая идея.
Ошибка вы видите наиболее определенно поднят, потому что multiprocessing модуль (кажись) использовать трубы для I NTER P roccess C ommunication и есть предел открытых труб/ФД.

Я предлагаю использовать интерпретатор питона без Global interpreter lock как Jython или IronPython и просто заменить multiprocessing модуль с threading один.


Если вы все еще хотите использовать multiprocessing модуль, вы можете использовать Proccess Pool, как это собрать возвращаемые значения:

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 модуля тоже ,

+0

Большое спасибо! Оно работает! –

2

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 и повышение настроек ulimit вашей оболочки.

+0

Я не думаю, что он запускает систему с тысячами процессорных ядер на OS X. – jsbueno

+1

Да, но он * пытается создать 10000 работников на OS X. – nneonneo

Смежные вопросы