gpt4 book ai didi

python - 复制列表时多处理 : why is a numpy array shared with the child processes,?

转载 作者:行者123 更新时间:2023-11-28 16:24:07 25 4
gpt4 key购买 nike

我用了这个script (见最后的代码)来评估当父进程被 fork 时,全局对象是否被共享或复制。

简而言之,脚本创建一个全局data 对象,子进程遍历data。该脚本还监控内存使用情况,以评估对象是否被复制到子进程中。

结果如下:

  1. data = np.ones((N,N))。子进程中的操作:data.sum()。结果:数据共享(无副本)
  2. data = list(range(pow(10, 8)))。子进程中的操作:sum(data)。结果:数据复制
  3. data = list(range(pow(10, 8)))。子进程中的操作:for x in data: pass。结果:数据复制

由于写时复制,结果 1) 是预期的。我对结果 2) 和 3) 有点困惑。为什么要复制 data


脚本

source

import multiprocessing as mp
import numpy as np
import logging
import os

logger = mp.log_to_stderr(logging.WARNING)

def free_memory():
total = 0
with open('/proc/meminfo', 'r') as f:
for line in f:
line = line.strip()
if any(line.startswith(field) for field in ('MemFree', 'Buffers', 'Cached')):
field, amount, unit = line.split()
amount = int(amount)
if unit != 'kB':
raise ValueError(
'Unknown unit {u!r} in /proc/meminfo'.format(u = unit))
total += amount
return total

def worker(i):
x = data.sum() # Exercise access to data
logger.warn('Free memory: {m}'.format(m = free_memory()))

def main():
procs = [mp.Process(target = worker, args = (i, )) for i in range(4)]
for proc in procs:
proc.start()
for proc in procs:
proc.join()

logger.warn('Initial free: {m}'.format(m = free_memory()))
N = 15000
data = np.ones((N,N))
logger.warn('After allocating data: {m}'.format(m = free_memory()))

if __name__ == '__main__':
main()

详细结果

运行 1 输出


[警告/MainProcess] 初始免费:25.1 GB
[警告/MainProcess] 分配数据后:23.3 GB
[WARNING/Process-2] 可用内存:23.3 GB
[WARNING/Process-4] 可用内存:23.3 GB
[WARNING/Process-1] 可用内存:23.3 GB
[WARNING/Process-3] 可用内存:23.3 GB

运行 2 输出


[警告/MainProcess] 初始免费:25.1 GB
[警告/MainProcess] 分配数据后:21.9 GB
[WARNING/Process-2] 可用内存:12.6 GB
[WARNING/Process-4] 可用内存:12.7 GB
[WARNING/Process-1] 可用内存:16.3 GB
[WARNING/Process-3] 可用内存:17.1 GB

运行3输出


[警告/MainProcess] 初始免费:25.1 GB
[警告/MainProcess] 分配数据后:21.9 GB
[WARNING/Process-2] 可用内存:12.6 GB
[WARNING/Process-4] 可用内存:13.1 GB
[WARNING/Process-1] 可用内存:14.6 GB
[WARNING/Process-3] 可用内存:19.3 GB

最佳答案

它们都是写时复制。你缺少的是当你这样做时,例如,

for x in data:
pass

data 中包含的每个对象的引用计数临时递增 1,一次一个,因为 x 依次绑定(bind)到每个对象。对于 int 对象,CPython 中的引用计数是基本对象布局的一部分,因此对象会被复制(您确实改变了它,因为引用计数发生了变化)。

为了更类似于 numpy.ones 的情况,尝试,例如,

data = [1] * 10**8

然后只有一个唯一对象被列表引用了很多次 (10**8),所以几乎没有什么可以复制的(同一个对象的引用计数多次递增和递减)。

关于python - 复制列表时多处理 : why is a numpy array shared with the child processes,?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37980870/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com