簡體   English   中英

python multiprocessing.Array:巨大的臨時內存開銷

[英]python multiprocessing.Array: huge temporary memory overhead

如果我使用python的multiprocessing.Array創建一個1G共享陣列,則會發現python進程在調用multiprocessing.Array期間使用了大約30G的內存,然后減少了內存使用量。 我將不勝感激,幫助您弄清為什么會發生這種情況並加以解決。

下面是在smem監視的內存下在Linux上重現它的代碼:

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

從打印語句的格式,您正在使用python 2

xrange(n)替換range(n)以節省一些內存。

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

(或使用python 3)

10億個范圍大約需要8GB(好吧,我只是在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)) 至少您不會錯誤地分配1 TB!

編輯:

OP注釋表示我的解釋無法解決問題。 我在Windows框上做了一些簡單的測試:

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

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

高達500Mb的坡道,然后使用python 2保持在250Mb。高達500Mb的坡道,然后通過python 3保持在7Mb(這很奇怪,因為它至少應為10Mb ...)

結論:好的,它的峰值為500Mb,因此不確定是否會有所幫助,但是您可以在Python 3上嘗試您的程序,看看您的整體內存峰值是否較少?

不幸的是,問題不僅僅在於范圍,我只是簡單地說明了一下。 實際上,該數據將從磁盤讀取。 我還可以使用n * [“ a”]並在multiprocessing.Array中指定c_char作為另一個示例。 當我傳遞給multiprocessing.Array的列表中只有1G數據時,仍然使用16G左右。 我想知道是否發生了一些效率低下的酸洗或類似的事情。

我似乎已經通過使用tempfile.SpooledTemporaryFile和numpy.memmap找到了一種解決方法。 我可以打開一個到內存中的臨時文件的內存映射,該文件在必要時被假脫機到磁盤,並通過將其作為參數傳遞給multiprocessing.Process在不同的進程之間共享。

我仍然想知道multiprocessing.Array是怎么回事。 我不知道為什么它將對1G數據陣列使用16G。

暫無
暫無

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

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