2016-08-05 10 views
2

Если я использую многопроцессор python.Array для создания общего массива 1G, я нахожу, что процесс python использует во время вызова многопроцессорного процесса около 30G памяти.Array, а затем уменьшает использование памяти после что. Я был бы признателен за любую помощь, чтобы понять, почему это происходит и обходиться.python multiprocessing.Array: огромные временные временные ресурсы памяти

Вот код, чтобы воспроизвести его на Linux, с памятью под наблюдением 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() 

Вот результат:

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

Если вы используете python 2, замените 'range (n)' на 'xrange (n)' –

ответ

3

Из формата операторах печати, вы используете Python 2

Замените range(n) на xrange(n), чтобы сэкономить память.

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

(или использование питона 3)

1 млрд диапазон занимает примерно 8 Гб (ну я просто пытался что на моем Windows PC и замер: просто не делайте этого!)

Пробовал с 10 ** 7 вместо того, чтобы просто быть уверены:

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

функция генератора как xrange не имеет никакой памяти, так как она обеспечивает значения один на один, когда итерация на.

В Python 3, они должны были быть сыт по горло этими проблемами, понял, что большинство людей использовали range, потому что они хотели генераторы, убили xrange и превратили range в генератор. Теперь, если вы действительно хотите выделить все номера, которые у вас есть, до list(range(n)). По крайней мере, вы не выделяете один терабайт по ошибке!

Edit:

ОП комментарий означает, что мое объяснение не решает проблему. Я сделал несколько простых тестов на моем окна коробке:

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

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

пандусов до 500Mb затем остается на 250Мб с питоном 2 Разгоняется до 500Mb затем остается в 7Мб с питоном 3 (что странно, так как она должна по крайней мере, be 10Mb ...)

Заключение: хорошо, оно достигает 500 МБ, поэтому не уверен, что это поможет, но можете ли вы попробовать свою программу на Python 3 и посмотреть, есть ли у вас меньше общих пиков памяти?

+1

К сожалению, проблема связана не столько с диапазоном, сколько я просто нарисовал это как простую иллюстрацию. В действительности эти данные будут считаны с диска. Я мог бы также использовать n * ["a"] и указать c_char в многопроцессорной обработке. Это все еще использует около 16G, когда у меня только 1G данных в списке, который я передаю многопроцессорности. Мне интересно, есть ли какое-то неэффективное травление или что-то в этом роде. – jeffdiamond

1

К сожалению, проблема заключается не столько в диапазоне, сколько в том, что я просто поставил это как простую иллюстрацию. В действительности эти данные будут считаны с диска. Я мог бы также использовать n * ["a"] и указать c_char в многопроцессорной обработке. Это все еще использует около 16G, когда у меня только 1G данных в списке, который я передаю многопроцессорности. Мне интересно, есть ли какое-то неэффективное травление или что-то в этом роде.

Кажется, я нашел обходное решение для того, что мне нужно, используя tempfile.SpooledTemporaryFile и numpy.memmap. Я могу открыть карту памяти временному файлу в памяти, который при необходимости намотан на диск, и поделиться им между различными процессами, передав его в качестве аргумента для многопроцессорной обработки.

Мне все еще интересно, что происходит с многопроцессорной обработкой. Я не знаю, почему он использовал 16G для массива данных 1G.

+0

Хорошо, так много для 'range'. Не могли бы вы опубликовать воспроизводимый и автономный пример? (ну, MVCE, как его здесь называют) –

+0

Я проверил больше. См. Мое последнее изменение –