在Matlab中截断大数组的内存有效方法

时间:2013-10-28 11:11:04

标签: arrays matlab memory truncate

我在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>

  • 有没有办法在不创建中间索引数组的情况下截断数组?
  • 如果没有,上述方法中的任何一种方法都比其他方法更节省内存(看起来不是这样)?如果是这样,为什么? Matlab 真的在两个例子中都创建了中间数组吗?

¹原因:我正在处理数据,但不知道要预分配多少。我做了一个有根据的猜测,经常我分配太多。我根据可用内存选择块大小,因为拆分更少的块意味着更快的代码。所以我想避免任何不必要的内存使用。另请参阅this post on allocating by chunk

1 个答案:

答案 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)

对于它们的价值,此NM的内存分析结果为:

enter image description here

好吧,就分配和释放的内存而言,看起来都是。也许这不是全部真相。

因此,出于好奇,我将M缩减为200(仅为200!),而不更改Nprofile clear并重申。分析声明:

enter image description here

有趣的是,Z=Z(1:M);现在几乎是瞬间的,Z(M:end)=[];更快一点。正如预期的那样,两者都可以释放大约2.4GB的内存。

最后,如果我们转向另一个方向并设置M=600000000;

enter image description here

现在,即使Z=Z(1:M);速度很慢,但两次Z(M:end)=[];一样快。

这表明:

  1. Z=Z(1:M);只抓取指定的元素,将它们存储在新缓冲区或临时变量中,释放旧缓冲区并将新/临时分配给数组Z。我只能通过增加 M并将N单独留下来,让我的4GB机器从2.45秒变为震动页面文件5分钟。对于小M/N,绝对更喜欢这个选项,可能在所有情况下。
  2. Z(M:end)=[];总是重写缓冲区,执行时间也会随着M而增加。实际上总是比较慢,并且似乎以指数增长,与Z=Z(1:M);不同。
  3. 内存分析不会提供有关这些内置操作的细粒度信息,也不应该被误解为在命令执行时释放和分配的内存总量,而是净更改。
  4. 更新1 :为了好玩,我在M的值范围内对测试进行了定时:

    enter image description here

    显然比剖析更具信息量。这两种方法都不是无操作,但是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.
    

    在每个指标(TotalAllocatedTotalFreedNumAllocs等)中,Z(M:end) = [];的效率低于Z=Z(1:M-1);。我希望通过检查NM这些值的这些数字来辨别内存中发生了什么,但我们猜测旧的MATLAB