부모 프로세스가 분기 될 때 전역 개체가 공유 또는 복사되는지 평가하려면이 코드를 script (끝에있는 코드 참조)이라고 사용했습니다.다중 처리 : 목록이 복사되는 동안 왜 numpy 배열이 하위 프로세스와 공유됩니까?
간단히 말해서 스크립트는 전체 data
개체를 만들고 하위 프로세스는 data
이상의 반복을 처리합니다. 스크립트는 또한 개체가 자식 프로세스에 복사되었는지 여부를 평가하기 위해 메모리 사용을 모니터링합니다.
data = np.ones((N,N))
:여기 결과이다. 하위 프로세스의 작업 :
data.sum()
. 결과 :data
은 공유 (복사 안 함)data = list(range(pow(10, 8)))
입니다. 하위 프로세스의 작업 :sum(data)
. 결과 :data
은 입니다.data = list(range(pow(10, 8)))
. 하위 프로세스의 작업 :for x in data: pass
. 결과 :data
은 입니다.
결과 1) copy-on-write 때문에 예상됩니다. 나는 결과 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 개 출력
012,384,365,417,471,
실행이 출력
[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
좋아, 그래서 나는 복사를 트리거하지 않고 간단한 조회를 반복하거나 할 수 없다. 쓸모없는 부분에 copy-on-write를 만들지 않습니까? –
COW (copy-on-write)는 Python이 그 기능을 지원하는 플랫폼에서'fork()'에서 상속받는 OS 개념이다. COW는 Python의 다중 처리 (mp)를 염두에두고 설계된 것이 아니며 Python의 mp는 COW를 염두에두고 설계되지 않았습니다 ;-) COW는 플랫폼에 따라 다르며 응용 프로그램에 따라 유용 할 수도 있고 그렇지 않을 수도 있습니다. CPython의 많은 객체 유형의 경우 refcount는 "객체의 데이터 대량으로 저장"되지 않습니다. 어쨌든 COW는 원래 exec-after-fork를 구현하기 위해 고안되었지만 이점은 방대한 부모 프로세스 데이터가 결코 참조되지 않는다는 것입니다. –