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