我正在运行一个创建大量数组的脚本。一切都运行良好,直到以下几行:
%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
。那么这里发生了什么?
答案 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
如果没有可重复的示例,很难确定问题的原因。可能是某些中间分配正在发生并非稀疏。或者你有一些我们在这里看不到的问题。