为什么MATLAB在设置预分配结构的字段时会不断消耗内存?

时间:2016-05-16 00:11:15

标签: matlab struct out-of-memory matlab-struct pre-allocation

我正在阅读AVI电影的帧并对其帧进行一些计算。这是我的代码的一部分:

clear; clc;
mov = mmreader('traffic.avi');

vidHeight = mov.Height;
vidWidth = mov.Width;
nFrames = mov.NumberOfFrames;
patchsize = 5;

frames(1:nFrames) = ...
    struct( ...
    'gray', zeros(vidHeight, vidWidth, 'double') ,...
    'dx', zeros(vidHeight, vidWidth, 'double') ,...
    'dy', zeros(vidHeight, vidWidth, 'double') ,...
    'dt', zeros(vidHeight, vidWidth, 'double') , ...
    'Sdx', zeros(vidHeight, vidWidth, 'double') , ...
    'Sdy', zeros(vidHeight, vidWidth, 'double') , ...
    'Sdt', zeros(vidHeight, vidWidth, 'double'));


h_sob_y = fspecial('sobel');
h_sob_x = h_sob_y';
h_sum = ones(patchsize);

for k = 1 : nFrames
    frames(k).gray = double(histeq(rgb2gray(read(mov, k))))/255;
    frames(k).dx = imfilter(frames(k).gray, h_sob_x);
    frames(k).dy = imfilter(frames(k).gray, h_sob_y);
    if k > 1
        frames(k).dt = frames(k).gray - frames(k-1).gray;
    end
    frames(k).Sdx = imfilter(frames(k).dx, h_sum);
    frames(k).Sdy = imfilter(frames(k).dy, h_sum);
    frames(k).Sdt = imfilter(frames(k).dt, h_sum);
end

问题是它在for循环中不断消耗内存。我首先怀疑read(mov, k),但这不是问题所在。我做的计算越多(我设置的字段越多),分配的内存就越多。图片显示,运行上面代码时分配的红色矩形显示内存,橙色代码用于相同的代码,最后3行注释(SdxSdySdt)。 whos方法显示在运行for循环之前和之后变量的数量或大小没有变化(k除外):

enter image description here

  Name           Size                 Bytes  Class       Attributes

  frames         1x120            129074848  struct                
  h_sob_x        3x3                     72  double                
  h_sob_y        3x3                     72  double                
  h_sum          5x5                    200  double                
  k              1x1                      8  double                
  mov            1x1                     60  mmreader              
  nFrames        1x1                      8  double                
  patchsize      1x1                      8  double                
  vidHeight      1x1                      8  double                
  vidWidth       1x1                      8  double                

当我添加更多字段时会变得更糟,它会占用所有内存并显示错误消息。

我错过了什么吗?我该如何防止这种情况?

BTW,我正在使用R2011a。

1 个答案:

答案 0 :(得分:2)

实际上 您将相同的结构分配给frames的所有条目。由于MATLAB在修改数据之前实际上不会生成副本,因此frames的所有元素都指向内存中的一个 struct

作为一个例子

a = [1,2,3];

%// No copy is made yet (memory usage remains the same)
b = a;

%// Copy is made and then modified (memory usage doubles)
b(1) = 2;

当您浏览循环并修改每个frame条目时,会生成并更新副本,从而导致您正在描述的内存使用情况发生变化。

如果您确实想要预分配数据,则需要使用类似repmat的内容,这样会强制复制初始化struct

frames = repmat(struct( ...
    'gray', zeros(vidHeight, vidWidth, 'double') ,...
    'dx', zeros(vidHeight, vidWidth, 'double') ,...
    'dy', zeros(vidHeight, vidWidth, 'double') ,...
    'dt', zeros(vidHeight, vidWidth, 'double') , ...
    'Sdx', zeros(vidHeight, vidWidth, 'double') , ...
    'Sdy', zeros(vidHeight, vidWidth, 'double') , ...
    'Sdt', zeros(vidHeight, vidWidth, 'double')), nFrames, 1);

就减少内存占用而言,这实际上取决于您尝试做的事情。可能只是因为您的视频太大而无法可靠地存储在内存中,您可能需要巧妙地存储和处理它以节省内存。