首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >多重处理:为什么在复制列表时,numpy数组与子进程共享?

多重处理:为什么在复制列表时,numpy数组与子进程共享?
EN

Stack Overflow用户
提问于 2016-06-23 01:33:58
回答 1查看 779关注 0票数 4

我使用这个script (请参阅末尾的代码)来评估父进程分叉时是否共享或复制了全局对象。

简单地说,脚本创建一个全局data对象,子进程在data上迭代。该脚本还监视内存使用情况,以评估对象是否在子进程中被复制。

以下是研究结果:

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

结果1)预期由于抄写。我对结果感到有点困惑。为什么要复制data

脚本

source

代码语言:javascript
复制
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输出

[WARNING/MainProcess] Initial free: 25.1 GB [WARNING/MainProcess] After allocating data: 23.3 GB [WARNING/Process-2] Free memory: 23.3 GB [WARNING/Process-4] Free memory: 23.3 GB [WARNING/Process-1] Free memory: 23.3 GB [WARNING/Process-3] Free memory: 23.3 GB

运行2输出

[WARNING/MainProcess] Initial free: 25.1 GB [WARNING/MainProcess] After allocating data: 21.9 GB [WARNING/Process-2] Free memory: 12.6 GB [WARNING/Process-4] Free memory: 12.7 GB [WARNING/Process-1] Free memory: 16.3 GB [WARNING/Process-3] Free memory: 17.1 GB

运行3输出

[WARNING/MainProcess] Initial free: 25.1 GB [WARNING/MainProcess] After allocating data: 21.9 GB [WARNING/Process-2] Free memory: 12.6 GB [WARNING/Process-4] Free memory: 13.1 GB [WARNING/Process-1] Free memory: 14.6 GB [WARNING/Process-3] Free memory: 19.3 GB

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2016-06-23 01:48:00

他们都是抄写的。你所缺少的是,当你这样做的时候,

代码语言:javascript
复制
for x in data:
    pass

data中包含的每个对象的引用计数暂时增加1,每次增加一个,因为x依次绑定到每个对象。对于int对象,CPython中的refcount是基本对象布局的一部分,因此该对象将被复制(您确实对其进行了变异,因为refcount发生了变化)。

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

代码语言:javascript
复制
data = [1] * 10**8

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

票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/37980870

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档