簡體   English   中英

多處理:為什么一個numpy數組與子進程共享,而一個列表被復制?

[英]Multiprocessing: why is a numpy array shared with the child processes, while a list is copied?

我使用這個腳本 (參見最后的代碼)來評估在父進程分叉時是共享還是復制全局對象。

簡而言之,該腳本創建一個全局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)。 我對結果2)和3)感到有些困惑。 為什么要復制data


腳本

資源

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

他們都是寫字復制品。 你缺少的是,當你這樣做時,例如,

for x in data:
    pass

data包含的每個對象的引用計數暫時遞增1,每次一個,因為x依次綁定到每個對象。 對於int對象,CPython中的refcount是基本對象布局的一部分,因此對象被復制(你確實改變了它,因為refcount改變了)。

為了使某些更類似於numpy.ones情況,請嘗試,例如,

data = [1] * 10**8

然后列表中只有一個唯一的對象引用了很多( 10**8 )次,因此復制很少(同一對象的引用計數會多次遞增和遞減)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM