我有三个大的列表。首先包含bitarrays(模块bitarray 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的RAM吗?
someFunction将从这些列表中读取一些值,然后根据读取的值执行一些计算。结果将返回到父进程。列表l1,l2和l3不会被某些函数修改。
因此,我会假设子流程不需要,也不会复制这些巨大的列表,而是将其与父级分享。这意味着由于linux下的copy-on-write方法,程序会占用16GB的RAM(不管我启动多少个子进程)? 我是否正确或我缺少会导致列表被复制的东西?
编辑: 在读完这个主题后,我仍然感到困惑。一方面,Linux使用copy-on-write,这意味着没有数据被复制。另一方面,访问对象将改变它的引用计数(我仍然不确定为什么以及这意味着什么)。即便如此,整个对象是否会被复制?
例如,如果我限定someFunction如下:
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以上(对于这些列表以及这些列表中的每个对象),直到程序退出。
所以,现在的问题是,我如何确保对象不会被复制到每个子流程?我可以禁用这些列表和这些列表中的每个对象的引用计数吗?
EDIT3只是一个额外的说明。子流程不需要修改l1
,l2
和l3
或这些列表中的任何对象。子流程只需要能够引用这些对象中的一些而不会导致为每个子流程复制存储器。
http://stackoverflow.com/questions/10721915/shared-memory-objects-in-python多处理类似的问题和你的答案。 – sean
重新回到底部,仍然不确定答案。整个对象是否会被复制?只有对象的一部分?只有包含refcount的页面?我如何检查? – FableBlaze
由于抄写时,我认为你不应该做任何特别的事情。为什么不试试呢? – NPE