【问题标题】:Matlab - Assignment into array causes error: "Maximum variable size allowed by the program is exceeded"Matlab - 分配到数组导致错误:“超出程序允许的最大变量大小”
【发布时间】:2011-09-08 03:33:59
【问题描述】:

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

%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。那么这里发生了什么?

【问题讨论】:

  • sig_dist 是标量吗?否则inserts 可能并不稀疏。
  • @Richie Cotton - 是的,当然,它是一个标量 - 它是高斯的“sigma”项:)

标签: matlab memory


【解决方案1】:

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

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

【讨论】:

  • 很好,我忘了 SPFUN.. 事实上,它是作为 M 文件实现的(不是内置的),如果你检查它的源代码,它和我做的完全一样: FIND 后跟 SPARSE :)
【解决方案2】:

MATLAB 实现了“延迟写入时复制”模型。让我用一个例子来解释。

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

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

现在,假设我们要创建另一个相同大小的向量:

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

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

???记不清。键入 HELP MEMORY 作为您的选项。

我们知道y 将需要5*1e7*8 = 400000000 bytes ~ 381.47 MBwhich 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 函数可以解决您的问题...

【讨论】:

  • 我真的希望你是对的,但是当我尝试做dist(5)=7(应该已经创建了矩阵的本地副本)时,它运行良好,没有错误。所以我想这不是原因。
  • 一定是你剩下的空闲连续内存太少了。理论上,我们希望索引和分配稀疏矩阵应该就地工作,而不涉及复制或转换为完整矩阵。不过,我认为这样的分配需要“一些”内存,我猜你正处于 MATLAB 无法分配完成操作所需的少量内存的地步。当然,这些都是我自己的猜测……我的建议是注意你的函数的内存占用,并尝试尽快清除不再需要的变量。
  • 我真的不知道该说什么。 memory 给我:Maximum possible array: 491 MB (5.147e+008 bytes) *dist(我正在处理的数组)的大小约为 3MB。所以我不明白发生了什么......
【解决方案3】:

一般来说,重新分配非稀疏元素不会改变矩阵的内存占用。分配前后致电whos查看。

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

如果没有可重现的示例,就很难确定问题的原因。可能正在发生一些不稀疏的中间分配。或者您有一些特定于您的问题的问题,我们在这里看不到。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-04-07
    • 2016-11-12
    • 2022-07-22
    • 2022-07-12
    • 1970-01-01
    • 1970-01-01
    • 2011-01-23
    相关资源
    最近更新 更多