我在Matlab中有一个大型(多GB)数组,我想截断¹。天真地,我认为截断不需要太多记忆,但后来我意识到它可能会:
>> Z = zeros(628000000, 1, 'single');
>> Z(364000000:end) = [];
Out of memory. Type HELP MEMORY for your options.
除非Matlab在截断Z
之前进行了一些巧妙的优化,否则此代码实际上创建一个数组(类型为double!)364000000:628000000
。我不需要这个数组,所以我可以改为:
>> Z = Z(1:363999999);
在这种情况下,第二个例子有效,并且对我来说没问题。但为什么有效呢?如果Z(364000000:end) = 0
由于中间数组364000000:628000000
所需的内存而失败,那么为什么Z = Z(1:363999999)
由于中间数组1:363999999
所需的内存而失败,即< EM>大?当然,我不需要这个中间数组,并且对于没有任何中间数组截断我的数组的解决方案感到满意,或者,如果Matlab优化了特定的方法,则会失败。< / p>
¹原因:我正在处理数据,但不知道要预分配多少。我做了一个有根据的猜测,经常我分配太多。我根据可用内存选择块大小,因为拆分更少的块意味着更快的代码。所以我想避免任何不必要的内存使用。另请参阅this post on allocating by chunk。
答案 0 :(得分:15)
我在带有profile('-memory','on');
的24GB内存的计算机上运行了这两个示例。此探查器选项将显示在每行代码上分配和释放的内存。这些应该是总不净额。我检查了一个简单的函数,它有net 0 free和alloc,它报告了总量。但是,似乎没有.m代码的内置命令支持它们不会向分析器提供细粒度的内存报告。
我为以下代码运行了几个测试:
% truncTest.m
N = 628000000;
M = 364000000;
clear Z
Z = zeros(N,1,'single');
Z(M:end) = [];
Z(1) % just because
clear Z
Z = zeros(N,1,'single');
Z = Z(1:M);
Z(1)
对于它们的价值,此N
和M
的内存分析结果为:
好吧,就分配和释放的内存而言,行看起来都是。也许这不是全部真相。
因此,出于好奇,我将M
缩减为200
(仅为200!),而不更改N
,profile clear
并重申。分析声明:
有趣的是,Z=Z(1:M);
现在几乎是瞬间的,Z(M:end)=[];
更快一点。正如预期的那样,两者都可以释放大约2.4GB的内存。
最后,如果我们转向另一个方向并设置M=600000000;
:
现在,即使Z=Z(1:M);
速度很慢,但两次与Z(M:end)=[];
一样快。
这表明:
Z=Z(1:M);
只抓取指定的元素,将它们存储在新缓冲区或临时变量中,释放旧缓冲区并将新/临时分配给数组Z
。我只能通过增加 M
并将N
单独留下来,让我的4GB机器从2.45秒变为震动页面文件5分钟。对于小M/N
,绝对更喜欢这个选项,可能在所有情况下。Z(M:end)=[];
总是重写缓冲区,执行时间也会随着M
而增加。实际上总是比较慢,并且似乎以指数增长,与Z=Z(1:M);
不同。 更新1 :为了好玩,我在M
的值范围内对测试进行了定时:
显然比剖析更具信息量。这两种方法都不是无操作,但是Z=Z(1:M);
是最快的,但它可以使用Z
的内存几乎加倍,M/N
接近1。
更新2 :
在R2008b之前的32位Windows中可以使用名为feature
(和mtic
)的相对未知的mtoc
。我仍然将它安装在一台机器上,所以我决定看看它是否提供了更多的洞察力,同时理解(a)从那以后发生了很大变化,(b)它是32位MATLAB中使用的完全不同的内存管理器。尽管如此,我还是将测试大小缩小到N=128000000; M=101000000;
并进行了查看。首先,feature mtic
Z=Z(1:M-1);
>> tic; feature mtic; Z=Z(1:M-1); feature mtoc, toc
ans =
TotalAllocated: 808011592
TotalFreed: 916009628
LargestAllocated: 403999996
NumAllocs: 86
NumFrees: 77
Peak: 808002024
Elapsed time is 0.951283 seconds.
清理,重新创建Z
,另一种方式:
>> tic; feature mtic; Z(M:end) = []; feature mtoc, toc
ans =
TotalAllocated: 1428019588
TotalFreed: 1536018372
LargestAllocated: 512000000
NumAllocs: 164
NumFrees: 157
Peak: 1320001404
Elapsed time is 4.533953 seconds.
在每个指标(TotalAllocated
,TotalFreed
,NumAllocs
等)中,Z(M:end) = [];
的效率低于Z=Z(1:M-1);
。我希望通过检查N
和M
这些值的这些数字来辨别内存中发生了什么,但我们猜测旧的MATLAB