【问题标题】:Why does MATLAB's permute not need extra memory?为什么 MATLAB 的置换不需要额外的内存?
【发布时间】:2016-03-17 15:36:58
【问题描述】:

置换操作需要输出一个不同的矩阵到输出,是not like reshape,这里数据没有被修改,permute确实修改了数据。

但是,如果测试多维排列的内存使用情况,它与使用的变量相同。所以,我的问题是,MATLAB 如何执行这种排列以避免使用任何额外的内存?

额外问题:MATLAB 有没有实际使用额外内存的场景?


测试代码:

function out=mtest() 
   out = ones(1e3,1e3,1e3); % Caution, 8Gb
   out=permute(out,[3 1 2]);
end 

调用它:

profile -memory on
a=mtest;
profreport

注意,它的 8Gb 数据。

【问题讨论】:

    标签: matlab


    【解决方案1】:

    您的论点有缺陷,因为 MATLAB 内存分析器没有告诉您真相!

    permute 方法实际上确实创建了矩阵的第二个副本,其中数据已置换并返回...

    我自己也试过了:

    • 在 Windows 10 中,我打开了“性能”选项卡上的“任务管理器”,并显示了“内存”图表。我还将“更新速度”设置为“高”以获得更精细的时间分辨率。

    • 我的笔记本电脑上只有 8 GB 的 RAM,所以为了避免颠簸,我将您的功能修改为:

      function out = mtest()
          out = rand([1e3,5e2,5e2]);  % about 1.8 GB = 1e3*5e2*5e2*8/2^30
          out = permute(out, [3 2 1]);
      end
      
    • 然后我将函数简单地运行为:

      %clear a
      a = mtest();
      

      并观察内存使用情况;它从使用中的 1.8 gigs 上升到 5.2 gigs,然后迅速下降到 3.6 gigs。这确认已创建副本。

    我还在perfmon.exe 下重复了测试,显示相同的模式:

    您可以看到函数在其峰值时的内存使用量是它返回时的两倍。

    虽然这并不是分析内存使用情况的最佳方法(最好使用适当的内存分析器,例如 Intel Inspector XE),但它确实在一定程度上表明permute 确实没有就地工作

    【讨论】:

    • 太棒了!我开始怀疑 MATLAB 是否在欺骗我,确实是这样!很高兴知道这个副本确实发生了。
    • 很好的答案!我猜permute 的程序员更喜欢速度而不是内存效率
    【解决方案2】:

    这只是一个猜测,因为我真的不知道 permute 在幕后做了什么。

    1. 维度的置换总是可以作为一系列基本置换操作来完成,其中“基本”意味着只交换两个维度。例如permute(x, [4 1 2 3])等价于这个基本置换操作序列(序列不唯一):

      permute(..., [4 2 3 1]) %// interchange dims 1 and 4: we have dims [4 2 3 1]
      permute(..., [1 4 3 2]) %// interchange dims 2 and 4: we have dims [4 1 3 2]
      permute(..., [1 2 4 3]) %// interchange dims 3 and 4: we have dims [4 1 2 3]
      
    2. 每个基本操作(交换二维)本质上都是沿多维数组的给定平面进行的转置,沿所有其他维度重复执行。

    3. 转置can be done inline,只需要固定数量的额外内存,与数组大小无关,或者随着数组大小增长非常缓慢。

    将这三个事实放在一起表明,在没有大量额外内存的情况下可能做到这一点。不过,这可能不是 Matlab 实际使用的方法。

    【讨论】:

    • 置换比转置快得多。我敢打赌它根本不会触及数组数据,只是改变了评估索引的顺序。如果你想转置一个 2D 实矩阵,那么不要做numrows*colindex+rowindex 来找出你的 1D 中的索引支持数组,您可以简单地切换到使用numcols*rowIndex+colindex。这将具有在不更改数据的情况下转置矩阵的外观。指定遍历维度顺序的数组可以很容易地与每个数组关联,而不是依赖于隐式 [1 2 3 4...N] 设计。
    • @KitsuneYMG 我知道你的意思,但是这个逻辑有一个缺陷:用那个“索引开关”索引一个数组对于内存读取缓存来说是非常昂贵的。如果确实发生了您所说的事情(就像它的索引更改方式一样),那么稍后在其他操作中使用该矩阵将导致性能大幅下降,因为它已被转置。而这种效果在MATLAB中是看不到的。我的猜测是转置更快,因为它使用了另一种算法。
    • 看到@Amros 的回答让人想知道是否可以创建一个函数mempermute 来实现内存感知置换
    • @AnderBiguri 我这样说是因为我最近需要在 MEX 函数的 C++ 端执行类似的置换操作(在列优先和行优先顺序之间转换一般 ND 数组),但我只是放弃并使用mexCallMATLAB 在MATLAB 中调用permute :) 这是一个接受任何顺序排列的通用函数,而不仅仅是简单的转置..
    • 我明白了.. 那么您可能有兴趣查看我们如何在 mexopencv 中在 OpenCV 的 cv::Mat/cv::MatND 和 MATLAB 的 mxArray 之间转换所有可能的情况(多-通道和/或多维):github.com/kyamagu/mexopencv/blob/master/src/MxArray.cpp#L529(参见toMattoMatND 方法)。
    猜你喜欢
    • 2015-02-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-08-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多