Python写时复制或访问时复制共享内存



我试图理解进程之间共享内存的工作原理,但我陷入了困境
我正在使用一个非常简单的测试程序c.py,并使用smem 跟踪内存

c.py:

import sys
import time
from multiprocessing import Process
arr = [x for x in range(int(1e6) * 50)]
print(sys.getsizeof(arr))  # 411943896
def f():
x = 0
for i in range(len(arr)):
#x += arr[i]
pass
time.sleep(10)
p = Process(target=f)
p.start()
p.join()

当我在x += arr[i]被注释掉的情况下运行它时,我看到了以下结果:

PID User     Command                         Swap      USS      PSS      RSS
1693779 1000     python /usr/bin/smem -n -t         0     8368     9103    14628
1693763 1000     python c.py                        0     1248   992816  1986688
1693749 1000     python c.py                        0     1244   993247  1989752
-------------------------------------------------------------------------------
3 1                                           0    10860  1995166  3991068

如果我理解正确的话,PSS告诉我,我的单个全局数组arr在两个进程之间共享,并且USS显示每个进程分配的唯一内存非常少。

然而,当我取消注释x += arr[i]时,仅访问子进程中的数组元素就会产生非常不同的结果:

PID User     Command                         Swap      USS      PSS      RSS
1695338 1000     python /usr/bin/smem -n -t         0     8476     9508    14392
1695296 1000     python c.py                       64  1588472  1786582  1986708
1695280 1000     python c.py                        0  1588644  1787246  1989520
-------------------------------------------------------------------------------
3 1                                          64  3185592  3583336  3990620

我不明白。访问数组似乎导致它被复制到子进程,这意味着python实际上是在访问时复制共享内存,而不是在写入时。

  1. 我的理解正确吗?访问全局变量arr时,arr数据所在的内存是否已复制到子进程?

  2. 如果是这样的话,子进程就没有办法在不加倍内存使用的情况下访问全局变量吗?

  3. 如果有人能解释smem报告的总体内存使用情况,我会很高兴,然而,在这种情况下,我希望这是一个更适合SU的问题?。如果进行简单的复制,我预计内存会翻倍,但每个进程显示的唯一内存为1588472,除此之外,整个PSS共享内存为2倍1786582,因此总计约为6750108?我确信我在这里的理解是错误的,但我不知道如何解释

正在写入元素。Python的标准实现使用引用计数,因此即使查看对象也需要写入其引用计数。

最新更新