Matlab - 分配到数组会导致错误:“超出程序允许的最大变量大小”

时间:2011-09-06 14:58:07

标签: matlab memory

我正在运行一个创建大量数组的脚本。一切都运行良好,直到以下几行:

%dist is a sparse matrix
inds=dist~=0;
inserts=exp(-dist(inds).^2/2*sig_dist);
dist(inds)=inserts;

最后一行导致错误:??? Maximum variable size allowed by the program is exceeded.

我不明白最后一行如何增加变量大小 - 请注意我只是在非零开始的地方插入矩阵dist。那么这里发生了什么?

3 个答案:

答案 0 :(得分:1)

MATLAB实现了“懒惰的写时复制”模型。让我用一个例子来解释。

首先,创建一个非常大的向量

x = ones(5*1e7,1);

现在,我们想要创建另一个相同大小的矢量:

y = ones(5*1e7,1);

在我的机器上,这将失败并出现以下错误

  

???内存不足。键入HELP MEMORY以获取选项。

我们知道y需要5*1e7*8 = 400000000 bytes ~ 381.47 MB(也由which x确认),但如果我们检查剩余的免费连续内存量:

>> memory
Maximum possible array:             242 MB (2.540e+008 bytes) *
Memory available for all arrays:    965 MB (1.012e+009 bytes) **
Memory used by MATLAB:              820 MB (8.596e+008 bytes)
Physical Memory (RAM):             3070 MB (3.219e+009 bytes)

*  Limited by contiguous virtual address space available.
** Limited by virtual address space available.

我们可以看到它超出了242 MB可用。

另一方面,如果你指定:

y = x;

它几乎可以立即成功。这是因为MATLAB实际上没有分配与x大小相同的另一个内存块,而是创建一个与y共享相同底层数据的变量x(事实上,如果你再次致电memory,您将看到几乎没有差异。)

一旦其中一个变量发生变化,MATLAB将只尝试制作另一个数据副本,因此如果您尝试这个相当无辜的赋值语句:

y(1) = 99;

它会抛出一个错误,抱怨内存不足,我怀疑你的情况正在发生......


编辑:

我能够通过以下示例重现该问题:

%# a large enough sparse matrix (you may need to adjust the size)
dist = sparse(1:3000000,1:3000000,1);

首先,让我们检查一下内存状态:

» whos
  Name            Size                    Bytes  Class     Attributes

  dist      3000000x3000000            48000004  double    sparse    

» memory
Maximum possible array:             394 MB (4.132e+008 bytes) *
Memory available for all arrays:   1468 MB (1.539e+009 bytes) **
Memory used by MATLAB:              328 MB (3.440e+008 bytes)
Physical Memory (RAM):             3070 MB (3.219e+009 bytes)

*  Limited by contiguous virtual address space available.
** Limited by virtual address space available.

说我们要将函数应用于所有非零元素:

f = @(X) exp(-X.^2 ./ 2);

奇怪的是,如果您尝试切片/分配,那么它将失败:

» dist(dist~=0) = f( dist(dist~=0) );
??? Maximum variable size allowed by the program is exceeded.

但是,以下赋值不会引发错误:

[r,c,val] = find(dist);
dist = sparse(r, c, f(val));

我仍然没有解释为什么在第一种情况下抛出错误,但是这样使用FIND函数可以解决你的问题......

答案 1 :(得分:1)

我不确定你为什么会看到这个错误。但是,我建议您使用Matlab函数spfun将函数应用于稀疏矩阵中的非零元素。例如:

>>dist = sprand(10000,20000,0.001);
>>f = @(x) exp(-x.^2/2*sig_dist);
>>dist = spfun(f,dist)

答案 2 :(得分:0)

通常,重新分配非稀疏元素不会改变矩阵的内存占用量。在分配前后调用whos进行检查。

dist = sparse(10, 10);
dist(1,1) = 99;
dist(6,7) = exp(1);
inds = dist ~= 0;
whos
dist(inds) = 1;
whos

如果没有可重复的示例,很难确定问题的原因。可能是某些中间分配正在发生并非稀疏。或者你有一些我们在这里看不到的问题。