2016-08-05 10 views
2

파이썬의 다중 처리 .Array를 사용하여 1G 공유 배열을 만드는 경우, 파이썬 프로세스가 multiprocessing.Array를 호출하는 동안 약 30G의 메모리를 사용하고, 그. 왜 이런 일이 일어나고 있는지 알아 내고 해결하기 위해 도움을 주시면 감사하겠습니다. 여기파이썬 다중 프로세싱. 배열 : 거대한 임시 메모리 오버 헤드

코드는 smem에 의해 모니터링 메모리, 리눅스에 재현하는 것입니다

import multiprocessing 
import ctypes 
import numpy 
import time 
import subprocess 
import sys 

def get_smem(secs,by): 
    for t in range(secs): 
     print subprocess.check_output("smem") 
     sys.stdout.flush() 
     time.sleep(by) 



def allocate_shared_array(n): 
    data=multiprocessing.Array(ctypes.c_ubyte,range(n)) 
    print "finished allocating" 
    sys.stdout.flush() 


n=10**9 
secs=30 
by=5 
p1=multiprocessing.Process(target=get_smem,args=(secs,by)) 
p2=multiprocessing.Process(target=allocate_shared_array,args=(n,)) 
p1.start() 
p2.start() 
print "pid of allocation process is",p2.pid 
p1.join() 
p2.join() 
p1.terminate() 
p2.terminate() 
다음

출력되어, 당신은 파이썬 2

pid of allocation process is 2285 
    PID User  Command       Swap  USS  PSS  RSS 
2116 ubuntu top        0  700  773  1044 
1442 ubuntu -bash        0  2020  2020  2024 
1751 ubuntu -bash        0  2492  2528  2700 
2284 ubuntu python test.py      0  1080  4566 11924 
2286 ubuntu /usr/bin/python /usr/bin/sm  0  4688  5573  7152 
2276 ubuntu python test.py      0  4000  8163 16304 
2285 ubuntu python test.py      0 137948 141431 148700 

    PID User  Command       Swap  USS  PSS  RSS 
2116 ubuntu top        0  700  773  1044 
1442 ubuntu -bash        0  2020  2020  2024 
1751 ubuntu -bash        0  2492  2528  2700 
2284 ubuntu python test.py      0  1188  4682 12052 
2287 ubuntu /usr/bin/python /usr/bin/sm  0  4696  5560  7160 
2276 ubuntu python test.py      0  4016  8174 16304 
2285 ubuntu python test.py      0 13260064 13263536 13270752 

    PID User  Command       Swap  USS  PSS  RSS 
2116 ubuntu top        0  700  773  1044 
1442 ubuntu -bash        0  2020  2020  2024 
1751 ubuntu -bash        0  2492  2528  2700 
2284 ubuntu python test.py      0  1188  4682 12052 
2288 ubuntu /usr/bin/python /usr/bin/sm  0  4692  5556  7156 
2276 ubuntu python test.py      0  4016  8174 16304 
2285 ubuntu python test.py      0 21692488 21695960 21703176 

    PID User  Command       Swap  USS  PSS  RSS 
2116 ubuntu top        0  700  773  1044 
1442 ubuntu -bash        0  2020  2020  2024 
1751 ubuntu -bash        0  2492  2528  2700 
2284 ubuntu python test.py      0  1188  4682 12052 
2289 ubuntu /usr/bin/python /usr/bin/sm  0  4696  5560  7160 
2276 ubuntu python test.py      0  4016  8174 16304 
2285 ubuntu python test.py      0 30115144 30118616 30125832 

    PID User  Command       Swap  USS  PSS  RSS 
2116 ubuntu top        0  700  771  1044 
1442 ubuntu -bash        0  2020  2020  2024 
1751 ubuntu -bash        0  2492  2527  2700 
2284 ubuntu python test.py      0  1192  4808 12052 
2290 ubuntu /usr/bin/python /usr/bin/sm  0  4700  5481  7164 
2276 ubuntu python test.py      0  4092  8267 16304 
2285 ubuntu python test.py      0 31823696 31827043 31834136 

    PID User  Command       Swap  USS  PSS  RSS 
2116 ubuntu top        0  700  771  1044 
1442 ubuntu -bash        0  2020  2020  2024 
1751 ubuntu -bash        0  2492  2527  2700 
2284 ubuntu python test.py      0  1192  4808 12052 
2291 ubuntu /usr/bin/python /usr/bin/sm  0  4700  5481  7164 
2276 ubuntu python test.py      0  4092  8267 16304 
2285 ubuntu python test.py      0 31823696 31827043 31834136 

Process Process-2: 
Traceback (most recent call last): 
    File "/usr/lib/python2.7/multiprocessing/process.py", line 258, in _bootstrap 
    self.run() 
    File "/usr/lib/python2.7/multiprocessing/process.py", line 114, in run 
    self._target(*self._args, **self._kwargs) 
    File "test.py", line 17, in allocate_shared_array 
    data=multiprocessing.Array(ctypes.c_ubyte,range(n)) 
    File "/usr/lib/python2.7/multiprocessing/__init__.py", line 260, in Array 
    return Array(typecode_or_type, size_or_initializer, **kwds) 
    File "/usr/lib/python2.7/multiprocessing/sharedctypes.py", line 115, in Array 
    obj = RawArray(typecode_or_type, size_or_initializer) 
    File "/usr/lib/python2.7/multiprocessing/sharedctypes.py", line 88, in RawArray 
    result = _new_value(type_) 
    File "/usr/lib/python2.7/multiprocessing/sharedctypes.py", line 63, in _new_value 
    wrapper = heap.BufferWrapper(size) 
    File "/usr/lib/python2.7/multiprocessing/heap.py", line 243, in __init__ 
    block = BufferWrapper._heap.malloc(size) 
    File "/usr/lib/python2.7/multiprocessing/heap.py", line 223, in malloc 
    (arena, start, stop) = self._malloc(size) 
    File "/usr/lib/python2.7/multiprocessing/heap.py", line 120, in _malloc 
    arena = Arena(length) 
    File "/usr/lib/python2.7/multiprocessing/heap.py", line 82, in __init__ 
    self.buffer = mmap.mmap(-1, size) 
error: [Errno 12] Cannot allocate memory 
+3

파이썬 2를 사용하는 경우'range (n)'을'xrange (n)'로 바꾸십시오. –

답변

3

인쇄 문장의 형식에서 사용하는

range(n)xrange(n)으로 바꿔서 일부 메모리를 절약하십시오.

10 억 범위는 약 8 기가 바이트합니다

data=multiprocessing.Array(ctypes.c_ubyte,xrange(n)) 

(또는 사용 파이썬 3) (잘 난 그냥 내 윈도우 PC에 얼어 것을 시도 : 그냥하지 마세요!)

가 시도 10 ** 7 대신 확실하게 : 반복시 때 하나씩 값을 제공하기 때문에

>>> z=range(int(10**7)) 
>>> sys.getsizeof(z) 
80000064 => 80 Megs! you do the math for 10**9 

xrange 같은 발전기 함수는 메모리를 취하지 않는다.

파이썬 3에서, 그들은 이러한 문제에 의해 공급되어 있어야합니다, 그들은 발전기를 원 xrange 사망하고 발전기에 range 설정되어 있기 때문에 대부분의 사람들이 range을 사용하는 것을 알아 냈다. 이제 모든 번호를 list(range(n))에 할당하려고합니다. 적어도 실수로 1 테라 바이트를 할당하지 마십시오!

편집 :

영업 코멘트는 내 설명이 문제가 해결되지 않는다는 것을 의미한다. 나는 나의 창 상자에 몇 가지 간단한 테스트를 만들었 : 다음 파이썬으로 250MB에서 다음 이상하다 파이썬 3 (와 7MB에서 유지까지이 500MB에 2 개 경사로를 유지이 500MB까지

import multiprocessing,sys,ctypes 
n=10**7 

a=multiprocessing.RawArray(ctypes.c_ubyte,range(n)) # or xrange 
z=input("hello") 

경사로가 적어도해야 이후 10Mb가 될 것 ...)

결론 : 괜찮습니까? 500Mb에서 최고점에 도달했기 때문에 도움이 될지 모르겠지만 Python 3에서 프로그램을 시험해보고 전반적인 메모리 부족이 없는지 확인하십시오.

+1

불행히도이 문제는 범위에 그다지 중요하지 않습니다. 실제로는 데이터를 디스크에서 읽습니다. 또한 n * [ "a"]를 사용하고 다중 처리에서 c_char를 지정할 수도 있습니다. 다른 예로서 배열. 그것은 여전히 ​​멀티 프로세싱에 전달할 목록에 1G의 데이터 만있을 때 약 16G를 사용합니다. 배열. 나는 비효율적 인 산세가 일어나고 있는지 또는 그런 식으로되어 있는지 궁금합니다. – jeffdiamond

1

불행히도, 그 문제는 범위에 그다지 그다지 간단하지 않습니다. 실제로는 데이터를 디스크에서 읽습니다. 또한 n * [ "a"]를 사용하고 다중 처리에서 c_char를 지정할 수도 있습니다. 다른 예로서 배열. 그것은 여전히 ​​멀티 프로세싱에 전달할 목록에 1G의 데이터 만있을 때 약 16G를 사용합니다. 배열. 나는 비효율적 인 산세가 일어나고 있는지 또는 그런 식으로되어 있는지 궁금합니다.

tempfile.SpooledTemporaryFile 및 numpy.memmap을 사용하여 필요한 해결 방법을 찾은 것 같습니다. 필자는 필요할 때 디스크에 스풀링 된 메모리의 임시 파일에 메모리 맵을 열어 다중 프로세스의 인수로 전달하여 여러 프로세스간에 공유 할 수 있습니다. 프로세스.

아직도 멀티 프로세싱과 관련하여 궁금한 점이 있습니다. 배열. 왜 1G 데이터 배열을 위해 16G를 사용할 지 모르겠습니다.

+0

좋아요, '범위'에 너무 많습니다. 재현 가능하고 독립 실행 형 예를 게시 할 수 있습니까? (글쎄, 여기 MVCE라고 부름) –

+0

더 많은 테스트를 거쳤습니다. 내 마지막 편집을 보아라. –