Python 写时复制或访问时复制共享内存
Python copy-on-write or copy-on-access shared memory
我试图了解进程之间共享内存的工作原理,但我被卡住了。
我正在使用一个非常简单的测试程序 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 实际上是在访问时复制共享内存,而不是在写入时复制。
我的理解对吗?访问全局变量arr
时,是否将arr
数据所在的内存复制到子进程?
如果是这样,子进程是否没有办法在不加倍内存使用的情况下访问全局变量?
如果有人能解释整体内存使用情况 smem 报告,我会很高兴,但是,在这种情况下,我希望它是一个更适合 SU? 的问题。如果进行简单复制,我希望内存加倍,但是每个进程显示的唯一内存为 1588472,除此之外,整体 PSS 共享内存为 2x 1786582,因此总计约为 6750108?我很确定我在这里的理解是非常错误的,但我不知道如何解释它。
您正在写入元素。 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 实际上是在访问时复制共享内存,而不是在写入时复制。
我的理解对吗?访问全局变量
arr
时,是否将arr
数据所在的内存复制到子进程?如果是这样,子进程是否没有办法在不加倍内存使用的情况下访问全局变量?
如果有人能解释整体内存使用情况 smem 报告,我会很高兴,但是,在这种情况下,我希望它是一个更适合 SU? 的问题。如果进行简单复制,我希望内存加倍,但是每个进程显示的唯一内存为 1588472,除此之外,整体 PSS 共享内存为 2x 1786582,因此总计约为 6750108?我很确定我在这里的理解是非常错误的,但我不知道如何解释它。
您正在写入元素。 Python 的标准实现使用引用计数,因此即使查看一个对象也需要写入其引用计数。