在Matlab中截取大数组的有效方法

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

在这种情况下,第二个例子有效,对我的目的来说很好。 但是它为什么起作用? 如果由于中间数组364000000:628000000所需的内存而导致Z(364000000:end) = 0失败,那么为什么Z = Z(1:363999999)由于中间数组1:363999999所需的内存而失败更大? 当然,我不需要这个中间数组,并且可以对无需任何中间数组而截断我的数组的解决方案感到满意,或者,如果Matlab优化了特定的方法,则会失败。

  • 有没有什么方法可以在不创建中间索引数组的情况下截断数组?
  • 如果不是,那么上述哪一种方法比另一种更具有内存效率(它看起来是)? 如果是这样,为什么? Matlab是否真的在两个例子中都创建了中间数组?

  • ¹原因:我正在处理数据,但不知道要预先分配多少。 我做了一个有教养的猜测,我经常分配太多。 我根据可用的内存来选择块大小,因为分割成更少的块意味着更快的代码。 所以我想避免任何不必要的内存使用。 另请参阅关于按块分配的帖子。


    我在配备24GB内存的机器上运行了两个例子profile('-memory','on'); 。 该分析器选项将显示分配的内存并在每行代码上释放内存。 这些应该是毛额而非净额。 我用一个简单的函数检查了净0免费和分配,并报告了总额。 但是,似乎内置命令不带.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的内存分析结果是:

    在这里输入图像描述

    那么,两条线在内存分配和释放方面看起来是一样的。 也许这不是全部的事实。

    所以,出于好奇,我把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(M:end)=[];

    这表明:

  • Z=Z(1:M); 只是捕获指定的元素,将它们存储在新的缓冲区或临时变量中,释放旧的缓冲区并将新/临时分配给数组Z 我能够让弱化的4GB机器从2.45秒变为5分钟,只需增加M并让N单独运行即可。 在所有情况下,肯定会选择小型M/N
  • Z(M:end)=[]; 总是重写缓冲区,并且执行时间也随着M增加。 实际上总是较慢,并且似乎以指数方式增加,不像Z=Z(1:M);
  • 内存分析并不提供有关这些内置操作的细粒度信息,不应将其误解为在命令执行中释放并分配的内存总量,而是净更改。
  • 更新1 :为了好玩,我在M的值范围内对测试进行计时:

    显然比分析更多的信息。 两种方法都不是无操作,但Z=Z(1:M); 是最快的,但它可以使用接近1的M/NZ的内存的两倍。

    更新2

    在R2008b之前,32位Windows中提供了一个称为mtic (和mtoc )的相对未知的feature 。 我仍然把它安装在一台机器上,所以我决定看看它是否提供了更多的见解,并且了解到(a)自那时以来发生了很大变化,(b)它是一个完全不同的32位MATLAB内存管理器。 不过,我将测试规模缩小到N=128000000; M=101000000; N=128000000; M=101000000; 并看了一下。 首先, Z=Z(1:M-1); 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

    链接地址: http://www.djcxy.com/p/29159.html

    上一篇: efficient way to truncate large array in Matlab

    下一篇: how to find similarity in more than 2 images