【问题标题】:MATLAB adding array elements iteratively: time behaviorMATLAB 迭代添加数组元素:时间行为
【发布时间】:2018-06-29 06:45:17
【问题描述】:

所以我知道这不是推荐的技术(预分配更好),但我对这种计时行为非常好奇;我很好奇幕后可能会发生什么。

在我的脑海中,向数组添加元素可能会根据实现在内存中引发几种不同的合理行为:(1) 摊销,添加元素需要相同的时间,例如在链表中添加元素维护一个指向最后一个元素的指针,(2)它可能会不时花费大量时间来预分配足够的内存,例如,列表中当前元素数量的两倍(如 Java 数组),(3)某些东西比我想象的还要聪明。

MATLAB 似乎做了一些我不太满意的事情。成本似乎呈线性增长,偶尔会出现峰值。关于它可能在做什么的任何猜测(或明智的解释)?我对模拟进行了平均(我认为,这可能隐藏了一些有趣的模式)。

当您迭代地将一个元素添加到最初为空的列表的末尾时,就会发生这种情况。为什么是线性增长?这些看似周期性的峰值是否有一个很酷的原因?

我用来生成它的代码:

% for averaging over
num_averages = 100000;
% number of simulations
num_sims = 10000;
% the time it takes to add one more item, array
time_store = nan(num_sims, num_averages);

% averaging count
for i = 1:num_averages

    % an array that grows with every loop
    building_array = [];

    for j = 1:num_sims
        tic;
        building_array = [building_array 1];
        time_store(j, i) = toc;
    end
end

plot(mean(time_store, 2)); hold all;
xlabel('Element num'); ylabel('Time');

【问题讨论】:

    标签: arrays matlab performance memory


    【解决方案1】:

    这真的很有趣!以非常规则的间隔存在峰值,并且曲线在其间或多或少是平坦的。在每个峰值之后,线都会上升一点。整洁的!我认为这与缓存行有关。您正在测量复制数组的成本,这大概与读取和写入缓存行的成本有关。

    如果换行

    building_array = [building_array 1];
    

    building_array(end+1) = 1;
    

    那么您将不会在每个迭代循环中复制数据,而是实际上将一个元素附加到数组中。通过这种更改,我得到了一条大部分平坦的线,峰值在对数增加的距离处(以及对数增加的高度),这与在需要时将数组大小加倍的常识实现一致:

    再解释一下:building_array = [building_array 1] 创建一个新数组,比building_array 大一个元素,并将building_array1 复制到其中。然后将其分配给building_array。看来 MATLAB 的 JIT 还没有针对这个 Code Pattern 进行优化!

    【讨论】:

    • 如果有人能解释这些尖峰,那就太好了。我了解高原,但不了解其间的高峰。
    • 也许 MATLAB 试图存储到连续的内存块?在重新分配更大的阵列(可能导致尖峰)时,挑战将变得越来越困难@ChrisLuengo
    • 假设:您可能还会在这里看到 C malloc 效果。当使用(end+1) 扩展数组时(并且该数组没有其他引用,因此它可以进行就地修改优化),即使它本身不进行填充,Matlab 也可能会调用 C 的realloc扩展原始数据数组,如果数组末尾有空闲的 malloc 管理空间,malloc 可以将其扩展到位。当 realloc 无法原地扩展并且必须将整个数组复制到其他地方以获得更大的连续内存块时,您会遇到峰值。
    • @AndrewJanke 有趣的想法。我们应该能够用malloc 做一个实验,看看我们是否得到相同的对数行为。不过,大小重复是 very 常规的。 ——哦,等等,你指的是OP的图表吗?每个增量都有一个副本,只是在某些特定尺寸下,复制操作比附近尺寸花费的时间更长。这是一种非常奇怪的行为!
    • @AndrewJanke 我花了一段时间才找到这个,使用了所有错误的关键字。但不知何故,我确实记得 MathWorks 的某个人为此写了一篇博客文章。这种优化是在 10 年前引入的。 blogs.mathworks.com/steve/2011/05/16/…
    猜你喜欢
    • 2016-11-30
    • 2020-03-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多