Как я могу ограничить объем процесса многопроцессорности?

Используя multiprocessing модуль python, следующий надуманный пример работает с минимальными требованиями к памяти:

 import multiprocessing # completely_unrelated_array = range(2**25) def foo(x): for x in xrange(2**28):pass print x**2 P = multiprocessing.Pool() for x in range(8): multiprocessing.Process(target=foo, args=(x,)).start() 

Раскомментируйте создание full_unrelated_array, и вы обнаружите, что каждый порожденный процесс выделяет память для копии completely_unrelated_array ! Это минимальный пример гораздо более крупного проекта, который я не могу понять, как обходиться; многопроцессорность, похоже, делает копию всего глобального. Мне не нужен объект общей памяти, мне просто нужно передать x и обработать его без накладных расходов памяти всей программы.

  • Доступ к стандартным выводам подпроцесса в python
  • В чем разница между многопроцессорностью и подпроцессом?
  • Многопроцессорный пул с итератором
  • Проблема развертывания программы Python (в комплекте с py2exe)
  • Повесьте скрипт Python с помощью SQLAlchemy и многопроцессорности
  • Ведение журнала с использованием многопроцессорности
  • Боковое наблюдение : интересно то, что print id(completely_unrelated_array) внутри foo дает одно и то же значение, предполагая, что каким-то образом это могут быть не копии …

  • Как я могу тестировать сообщения django?
  • Печать всех экземпляров класса
  • "SyntaxError: non-keyword arg after keyword arg" Ошибка в Python при использовании запросов.post ()
  • Какова цель самого себя?
  • Интерфейс Python для PayPal - urllib.urlencode не-ASCII-символы с ошибкой
  • matplotlib autoscale (ось = 'y') после участка нарезки с помощью set_xlim ()
  • 2 Solutions collect form web for “Как я могу ограничить объем процесса многопроцессорности?”

    Из-за природы os.fork() любые переменные в глобальном пространстве имен вашего модуля __main__ будут наследоваться дочерними процессами (при условии, что вы находитесь на платформе Posix), поэтому вы увидите использование памяти у детей отразите это, как только они будут созданы. Я не уверен, что вся эта память действительно выделяется, насколько я знаю, что память разделяется до тех пор, пока вы на самом деле не попытаетесь изменить ее в ребёнке, после чего будет создана новая копия. Windows, с другой стороны, не использует os.fork() – он повторно импортирует основной модуль в каждом дочернем os.fork() любые локальные переменные, которые вы хотите отправить детям. Таким образом, используя Windows, вы можете фактически избежать того, что большой глобальный конец копируется в дочерний элемент, только определяя его внутри if __name__ == "__main__": guard, потому что все внутри этого защитника будет выполняться только в родительском процессе:

     import time import multiprocessing def foo(x): for x in range(2**28):pass print(x**2) if __name__ == "__main__": completely_unrelated_array = list(range(2**25)) # This will only be defined in the parent on Windows P = multiprocessing.Pool() for x in range(8): multiprocessing.Process(target=foo, args=(x,)).start() 

    Теперь, в Python 2.x, вы можете создавать новые multiprocessing.Process объекты .Process путем форкирования, если вы используете платформу Posix. Но на Python 3.4 вы можете указать, как создавать новые процессы, используя контексты. Итак, мы можем указать контекст "spawn" , который используется Windows, для создания наших новых процессов и использования того же трюка:

     # Note that this is Python 3.4+ only import time import multiprocessing def foo(x): for x in range(2**28):pass print(x**2) if __name__ == "__main__": completely_unrelated_array = list(range(2**23)) # Again, this only exists in the parent ctx = multiprocessing.get_context("spawn") # Use process spawning instead of fork P = ctx.Pool() for x in range(8): ctx.Process(target=foo, args=(x,)).start() 

    Если вам нужна поддержка 2.x или вы хотите использовать os.fork() для создания новых объектов Process , я думаю, что лучшее, что вы можете сделать, чтобы отключить использование записанной памяти, сразу же удаляет оскорбительный объект в дочернем объекте:

     import time import multiprocessing import gc def foo(x): init() for x in range(2**28):pass print(x**2) def init(): global completely_unrelated_array completely_unrelated_array = None del completely_unrelated_array gc.collect() if __name__ == "__main__": completely_unrelated_array = list(range(2**23)) P = multiprocessing.Pool(initializer=init) for x in range(8): multiprocessing.Process(target=foo, args=(x,)).start() time.sleep(100) 

    Здесь важна та платформа, на которую вы нацеливаетесь. Процессы Unix-систем создаются с использованием памяти Copy-On-Write (корова). Поэтому, несмотря на то, что каждый процесс получает копию полной памяти родительского процесса, эта память фактически распределяется только на основе каждой страницы (4KiB), когда она модифицируется. Поэтому, если вы ориентируетесь только на эти платформы, вам ничего не нужно менять.

    Если вы ориентируетесь на платформы без вилок, вы можете использовать python 3.4 и новые контексты forkserver spawn и forkserver , см. Документацию. Эти методы будут создавать новые процессы, которые не имеют ничего общего или имеют ограниченное состояние с родителем, а вся передача данных явно.

    Но не то, что порожденный процесс будет импортировать ваш модуль, чтобы все глобальные данные были явно скопированы, и копирование на запись не возможно. Чтобы предотвратить это, вам необходимо уменьшить объем данных.

     import multiprocessing as mp import numpy as np def foo(x): import time time.sleep(60) if __name__ == "__main__": mp.set_start_method('spawn') # not global so forks will not have this allocated due to the spawn method # if the method would be fork the children would still have this memory allocated # but it could be copy-on-write completely_unrelated_array = np.ones((5000, 10000)) P = mp.Pool() for x in range(3): mp.Process(target=foo, args=(x,)).start() 

    например, верхний вывод с икру:

     %MEM TIME+ COMMAND 29.2 0:00.52 python3 0.5 0:00.00 python3 0.5 0:00.00 python3 0.5 0:00.00 python3 

    и с вилкой:

     %MEM TIME+ COMMAND 29.2 0:00.52 python3 29.1 0:00.00 python3 29.1 0:00.00 python3 29.1 0:00.00 python3 

    обратите внимание, как его более 100% из-за копирования на запись

    Python - лучший язык программирования в мире.