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

标签 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 所需的内存而失败,即更大?当然,我需要这个中间数组,我会很高兴有一种解决方案可以截断我的数组而没有任何中间数组,或者如果 Matlab 优化了特定方法,则失败了。

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

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

最佳答案

我在具有 profile('-memory','on'); 的 24GB RAM 机器上运行了这两个示例。此分析器选项将显示在每一行代码上分配和释放的内存。这些应该是总额而不是 Netty 。我检查了一个简单的函数,它有 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)

对于它们的值(value),此 NM 的内存分析结果是:

enter image description here

嗯,就分配和释放的内存而言,这两行看起来是相同的。也许这不是全部真相。

所以,出于好奇,我在不更改 N 的情况下将 M 减少到 200(只有 200 个!),profile 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。我能够通过 increasing M 并单独留下 N 使我较弱的 4GB 机器从 2.45 秒变为 5 分钟的页面文件抖动.对于小的 M/N,绝对更喜欢这个选项,可能在所有情况下。
  2. Z(M:end)=[]; 总是重写缓冲区,执行时间也随着 M 的增加而增加。实际上总是更慢,而且似乎呈指数增长,这与 Z=Z(1:M); 不同。
  3. 内存分析不会提供有关这些内置操作的细粒度信息,不应被误解为在命令执行过程中释放和分配的内存总量,而是净变化。

更新 1:只是为了好玩,我在 M 的值范围内对测试进行计时:

enter image description here

显然比分析提供更多信息。两种方法都不是空操作,但是 Z=Z(1:M); 最快,但是对于 M 可以使用几乎是 Z 两倍的内存/N 在 1 附近。

更新 2:

在 R2008b 之前的 32 位 Windows 中提供了一个相对未知的 feature,称为 mtic(和 mtoc)。我仍然将它安装在一台机器上,所以我决定看看这是否能提供更多洞察力,因为我知道(a)从那时起发生了很大变化,(b)它是 32 位 MATLAB 中使用的完全不同的内存管理器。尽管如此,我还是将测试大小减小到 N=128000000; M=101000000; 看看。一、feature mtic for 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

关于arrays - 在 Matlab 中截断大数组的内存有效方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19633192/

相关文章:

java - 如何在 Java 中创建内存高效的数据结构

javascript - 在 JavaScript 中一起使用过滤器和排序方法时排序不正确

MATLAB - 重新定义 YTickLabel

matlab - 我需要在调用 fft 或 ifft 之前调用 fftshift 吗?

objective-c - NSString指针: theoretical questions after study

memory - [ARM CortexA]强序和设备内存类型的区别

arrays - 将 pandas 数据帧转换为 numpy ndarray

javascript - 对关联数组的关联数组执行 foreach

java - 计算数组中的元素数

matlab - worker 数量增加——绩效下降