如果我使用python的multiprocessing.Array来创建1G共享数组,我发现python进程在调用多处理过程中使用了大约30G的内存。然后在此之后减少内存使用量。我很感激任何帮助,弄清楚为什么会这样,并解决它。
以下是在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
答案 0 :(得分:3)
从print语句的格式来看,您正在使用python 2
将range(n)
替换为xrange(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))
。至少你不会错误地分配一个太字节!
编辑:
OP评论意味着我的解释并没有解决问题。我在我的windows box上做了一些简单的测试:
import multiprocessing,sys,ctypes
n=10**7
a=multiprocessing.RawArray(ctypes.c_ubyte,range(n)) # or xrange
z=input("hello")
使用python 2,最高可达500Mb,然后保持250Mb 斜坡高达500Mb然后使用python 3保持在7Mb(这很奇怪,因为它至少应该是10Mb ......)
结论:好吧,它在500Mb达到峰值,所以不确定它会有所帮助,但是你可以在Python 3上尝试你的程序,看看你的整体内存峰值是否较少?
答案 1 :(得分:1)
不幸的是,问题不在于范围,因为我只是将其作为一个简单的说明。实际上,该数据将从磁盘中读取。我也可以使用n * [“a”]并在multiprocessing.Array中指定c_char作为另一个例子。当我在列表中只有1G的数据时,我仍然使用大约16G,我正在传递给multiprocessing.Array。我想知道是否有一些低效的酸洗正在进行或类似的事情。
我似乎通过使用tempfile.SpooledTemporaryFile和numpy.memmap找到了我需要的解决方法。我可以打开内存映射到内存中的临时文件,必要时将其假脱机到磁盘,并通过将其作为参数传递给multiprocessing.Process在不同进程之间共享。
我仍然想知道多处理会发生什么。尽管如此。我不知道为什么它会将16G用于1G数据阵列。