我有三个大型列表。第一个包含位数组(模块位数组0.8.0) ,另外两个包含整数数组。
l1=[bitarray 1, bitarray 2, ... ,bitarray n]
l2=[array 1, array 2, ... , array n]
l3=[array 1, array 2, ... , array n]
这些数据结构占用了相当多的 RAM (总共约16GB)。
如果我使用以下方法启动12个子进程:
multiprocessing.Process(target=someFunction, args=(l1,l2,l3))
这是否意味着将为每个子进程复制 l1、 l2和 l3,或者子进程将共享这些列表?或者更直接地说,我将使用16GB 还是192GB 的内存?
有些函数将从这些列表中读取一些值,然后根据读取的值执行一些计算。结果将返回到父进程。列表 l1、 l2和 l3不会被 some 函数修改。
因此,我会假设子进程不需要,也不会复制这些巨大的列表,而只是与父进程共享它们。也就是说,由于 Linux 采用写上复制的方法,程序将占用16GB 的 RAM (不管我启动多少个子进程) ? 我说的对吗,还是我遗漏了什么,导致名单被复制?
编辑: 在读了一些关于这个主题的书之后,我仍然感到困惑。一方面,Linux 使用写复制,这意味着不会复制任何数据。另一方面,访问对象将改变其引用计数(我仍然不确定为什么和什么意思)。即便如此,整个对象会被复制吗?
例如,如果我像下面这样定义一些函数:
def someFunction(list1, list2, list3):
i=random.randint(0,99999)
print list1[i], list2[i], list3[i]
使用这个函数是否意味着将为每个子进程完全复制 l1、 l2和 l3?
有办法检查这个吗?
EDIT2 在读取更多信息并监视子进程运行时系统的总内存使用情况之后,似乎确实为每个子进程复制了整个对象。这似乎是因为引用计数。
在我的程序中,l1、 l2和 l3的引用计数实际上是不需要的。这是因为在父进程退出之前,l1、 l2和 l3将保存在内存中(不变)。在此之前,不需要释放这些列表使用的内存。事实上,我确信引用计数将保持在0以上(对于这些列表和这些列表中的每个对象) ,直到程序退出。
所以现在的问题是,我怎样才能确保对象不会被复制到每个子进程?我是否可以禁用这些列表和这些列表中的每个对象的引用计数?
只是一个附加说明。子进程不需要修改 l1
、 l2
和 l3
或这些列表中的任何对象。子进程只需要能够引用其中的一些对象,而不会导致为每个子进程复制内存。