共享内存和多处理

时间:2017-05-28 21:44:22

标签: python multiprocessing shared-memory reference-counting

this question及其答案,我我理解为什么这个python代码:

<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.6.1/angular.min.js"></script>

<div ng-app="app">
    <main-component></main-component>
</div>

在执行期间继续使用越来越多的内存:这是因为子进程将引用计数更新为循环中的共享内存对象,触发了“写时复制”机制(我可以通过查看来减少空闲内存量) big_list = [ {j: 0 for j in range(200000)} for i in range(60) ] def worker(): for dic in big_list: for key in dic: pass print "." time.sleep(0.2) w = multiprocessing.Process(target=worker) w.start() time.sleep(3600) )。

然而,我不明白的是,如果迭代发生在父级而不是子级中,同样的事情会发生:

cat /proc/meminfo | grep MemFree

孩子甚至不需要知道def worker(): time.sleep(3600) w = multiprocessing.Process(target=worker) w.start() for dic in big_list: for key in dic: pass print "." time.sleep(0.2) 存在

在这个小例子中,我可以通过将big_list放在子函数中来解决问题,但有时变量引用不像这样可以访问,所以事情变得复杂。

为什么会发生这种机制,我该如何正确地避免它?

1 个答案:

答案 0 :(得分:2)

fork()之后,父母和孩子都会&#34;看到&#34;相同的地址空间。第一次 更改公共地址的内存时,写时复制(COW)机制必须克隆包含该地址的页面。因此,出于创建COW页面的目的,突变是发生在孩子还是父母身上并不重要。

在您的第二个代码段中,您遗漏了最重要的部分:确切地创建了big_list的位置。既然你说你可以在孩子身上躲过del big_list,那么big_list可能在分叉工作流程之前就存在了。如果是这样,那么 - 如上所述 - 对于您的症状而言,在父母或孩子中是否修改big_list并不重要。

要避免这种情况,请在创建子进程后创建big_list 。然后它所居住的地址空间不会被共享。或者,在Python 3.4或更高版本中,使用multiprocessing.set_start_method('spawn')。然后fork()不会被用来创建子进程,根本没有共享地址空间(在Windows上总是如此,它没有fork())。< / p>