2010-07-21 55 views
10

我在Matlab中遇到了一些内存管理问题。最后,它导致没有足够的可用内存和错误。我试图找出问题并找到了一个有趣的“功能”:不知何故,我在Matlab中释放了免费的内存。Matlab:调用函数后自由内存丢失

我做到以下几点:
1)运行MATLAB
2)键入 “记忆”,我得到:最大可能的数组:1293 MB,可用内存为所有阵列:1456 MB
3)我会打电话给一个功能。该功能相当长,所以很难粘贴在这里。但基本上它加载5加。 300mb mat文件(按顺序),挑选一些值并返回它们。返回的矩阵是ca. 1,2mb(4650x35双)
4)我清除工作区中的所有变量(“全部清除”)
5)输入“memory”我得到:可能的最大数组:759 mb,可用于所有阵列的存储器:1029 mb

如果我重复步骤3)到5),记忆数是恒定的。

那么这里有什么问题?我在哪里放松400MB的免费空间? Matlab使用的内存恒定在330mb左右。

有没有人有一些想法这里有什么问题?或者这是完全自然的东西,但我想念它?

感谢
托马斯

PS:我用Matlab 2010A和Win 7 32位专业版。

回答

16

这个“丢失”的内存很大一部分可能是由于内存碎片。随着Matlab在会话过程中分配和释放数组,内存被分解成更小的区域,并且在Matlab和底层C级别的内存管理器中,有些内存会被浪费掉。开销不被计算为由Matlab使用,因为它不用于保存M代码数组值。一些内存也可能由Matlab加载额外的M文件和库,分配内部缓冲区或结构,或者通过在Matlab的嵌入式JVM中扩展Java堆来消耗。这个是正常的。在完成一些工作之后,Matlab将不会像在新的会话中那样获得尽可能多的内存。 AFAIK,一旦发生低级碎片,除了重新启动Matlab之外,没有什么可以做到的。分配大量小阵列可加速碎片。如果使用大型单元或大型对象数组,有时会发生这种情况。因此,如果遇到问题,您可能需要通过将工作分解为更小的块,减少小区使用等来降低功能中的峰值内存使用量。如果MAT文件中有大的cellstr数组,则将它们转换为char。分配的“高水位”是支配碎片的因素,因此如果您可以将数据集分成更小的块,则可以将其放入更少的内存中。

在您的功能中,清除尽可能多的从一个MAT文件进入下一个之前。隐式做到这一点的一种方法是将每个文件处理移动到一个子功能中,如果它目前正坐在主功能的循环中。

为了帮助调试,请执行“dbstop if all error”,这将由OOM触发。从那里,您可以使用whos和调试器来查明当您耗尽内存时正在占用的空间。这可能会揭示需要清理的临时变量,或者提出分块工作的方法。

如果您想尝试查看哪些碎片看起来像以及它如何影响memory()的输出,下面是一个只会创建一些碎片的函数。

function fragmem(nbytes, chunksize) 
%FRAGMEM Fragment the Matlab session's memory 
if nargin < 2; chunksize = 1*2^10; end 

nbytes = nbytes - rem(nbytes, chunksize); 

nsteps = 100; % to make initial input relatively small 
c = cell([1 nsteps]); 
stepsize = nbytes/nsteps; 
chunksperstep = ceil(stepsize/chunksize); 
fprintf('Fragmenting %d MB memory into %d KB chunks (%d steps of %d chunks)\n',... 
    round(nbytes/2^20), round(chunksize/2^10), nsteps, chunksperstep); 

x = zeros([1 chunksperstep * chunksize], 'uint8'); 
colsizes = repmat(chunksize, [1 chunksperstep]); 
for i = 1:nsteps 
    c{i} = mat2cell(x, 1, colsizes); 
end 

Fragging 300 MB在我的机器上1KB块再现一个你所看到的大小我的Win32的机器上“损失”。

>> memory 
Maximum possible array:   1384 MB (1.451e+009 bytes) * 
Memory available for all arrays: 1552 MB (1.627e+009 bytes) ** 
Memory used by MATLAB:    235 MB (2.463e+008 bytes) 
Physical Memory (RAM):    3311 MB (3.472e+009 bytes) 

>> fragmem(300*2^20) 
Fragmenting 300 MB memory into 1 KB chunks (100 steps of 3072 chunks) 
>> memory 
Maximum possible array:   1009 MB (1.059e+009 bytes) * 
Memory available for all arrays: 1175 MB (1.232e+009 bytes) ** 
Memory used by MATLAB:    257 MB (2.691e+008 bytes) 
Physical Memory (RAM):    3311 MB (3.472e+009 bytes) 

>> 
+0

+1没有你尝试调用'pack'事后http://www.mathworks.com/access/helpdesk/help/techdoc/ref/pack.html – Amro 2010-07-21 17:45:13

+2

包()只是重新安排Matlab的数组,其目前分配。由于已释放数组的剩余部分,它没有解决这种较低级别的碎片问题,并且在fragmem()例子之后影响可以忽略不计。 (至少在我使用的Windows上)。顺便说一句,Matlab的doco真的不会谈论这种较低级别的碎片;我在写什么,我从外部接口doco推断出来,并尝试使用Matlab和C.Catatat emptor。 – 2010-07-21 18:34:02

+0

“为了帮助调试,请执行”dbstop if all error“,这将由OOM触发。从那里,您可以使用whos和调试器来查找当您耗尽内存时空间正在占用的位置。揭示需要清理的临时变量,或者提出分块工作的方法。“ 有趣的是,当我用完内存时,工作区很干净。上面的功能真的减少了可用内存,但没有在工作区中有很多变量... 这是一种讨厌有足够的内存..原则.. – Thomas 2010-07-22 08:26:34