9

我想将一个相当大的数据结构加载到一个进程中,然后分叉以希望减少总内存消耗。会os.fork以这种方式工作还是复制 Linux (RHEL) 中的所有父进程?

4

2 回答 2

24

即使使用了 COW,CPython 也使用引用计数并将引用计数存储在每个对象的标头中。因此,除非您不对该数据进行任何操作,否则您很快就会对相关内存进行虚假写入,这将迫使系统复制数据。将其传递给函数?那是另一个引用,一个INCREF,一个对 COW 内存的写入。将其存储在变量或对象属性中?相同的。哪怕只是查找一个方法就可以了?同上。由于各种原因,一些内置数据结构将它们的大部分数据与对象(例如大多数集合)分开分配。如果这些最终出现在不同的页面上——或者任何粒度的 COW 工作——你可能会很幸运。但是,从这样的集合中引用的对象也不例外——使用它来操作它的引用计数是一样的。

此外,将共享一些数据,因为没有设计写入它(例如,本机 CPython 代码),并且您fork的进程未触及的某些对象可能是共享的(老实说,我不确定;我认为循环 GC 不会写入对象)。但是 Python 代码使用的 Python 对象几乎可以保证被写入。类似的推理适用于 PyPy、Jython、IronPython 等(只是它们在对象头中摆弄位而不是进行引用计数),尽管我不能保证所有可能的配置。

于 2013-02-18T17:37:10.450 回答
3

如果您在 *nix 系统上,那么os.fork()将使用系统fork()调用,至少在 Linux 的情况下,它是写时复制:

http://linux.die.net/man/2/fork

见“注释”部分

于 2013-02-18T17:23:20.047 回答