将元素附加到数组的最快方法是什么?

时间:2014-12-26 13:17:13

标签: matlab optimization append

这是How to append an element to an array in MATLAB?的后续问题。该问题解决了 如何将元素附加到数组中。这里讨论了两种方法:

A = [A elem]  % for a row array
A = [A; elem] % for a column array

A(end+1) = elem;

第二种方法具有与行和列阵列兼容的明显优势。

然而,这个问题是:这两种方法中哪一种最快?我的直觉告诉我第二种方法是,但我想要一些证据支持或反对。有什么想法吗?

3 个答案:

答案 0 :(得分:4)

第二种方法(A(end+1) = elem)更快

根据以下基准(使用timeit benchmarking function from File Exchange运行),第二种方法(A(end+1) = elem)更快,因此应该首选。

有趣的是,尽管如此,两种方法之间的性能差距在旧版MATLAB中要比在最新版本中差得多

R2008a

enter image description here

R2013a

benchmark run in MATLAB R2013a

基准代码

function benchmark

    n = logspace(2, 5, 40);
    % n = logspace(2, 4, 40); 
    tf = zeros(size(n));
    tg = tf;

    for k = 1 : numel(n)
        x = rand(round(n(k)), 1);

        f = @() append(x);
        tf(k) = timeit(f);

        g = @() addtoend(x);
        tg(k) = timeit(g);
    end

    figure
    hold on
    plot(n, tf, 'bo')
    plot(n, tg, 'ro')
    hold off
    xlabel('input size')
    ylabel('time (s)')
    leg = legend('y = [y, x(k)]', 'y(end + 1) = x(k)');
    set(leg, 'Location', 'NorthWest');
end

% Approach 1: y = [y, x(k)];
function y = append(x)
    y = [];
    for k = 1 : numel(x);
        y = [y, x(k)];
    end
end

% Approach 2: y(end + 1) = x(k);
function y = addtoend(x)
    y = [];
    for k = 1 : numel(x);
        y(end + 1) = x(k);
    end
end

答案 1 :(得分:2)

这个怎么样?

function somescript

RStime = timeit(@RowSlow)
CStime = timeit(@ColSlow)
RFtime = timeit(@RowFast)
CFtime = timeit(@ColFast)

function RowSlow

rng(1)

A = zeros(1,2);
for i = 1:1e5
    A = [A rand(1,1)];
end

end

function ColSlow

rng(1)

A = zeros(2,1);
for i = 1:1e5
    A = [A; rand(1,1)];
end

end

function RowFast

rng(1)

A = zeros(1,2);
for i = 1:1e5
    A(end+1) = rand(1,1);
end

end

function ColFast

rng(1)

A = zeros(2,1);
for i = 1:1e5
    A(end+1) = rand(1,1);
end

end

end

对于我的机器,这会产生以下时间:

RStime =

30.4064

CStime =

29.1075

RFtime =

0.3318

CFtime =

0.3351

矢量的方向似乎并不重要,但第二种方法在我的机器上快了大约100倍。

答案 2 :(得分:1)

除了上面指出的快速增长方法(即A(k+1))之外,您还可以通过将数组大小增加一些倍数来提高速度,以便随着大小的增加分配变得更少。 / p>

在使用R2014b的笔记本电脑上,有条件的大小加倍导致速度增加约6倍:

>> SO

GATime =
    0.0288

DWNTime =
    0.0048

在实际应用中,A的大小需要限制为所需的大小,或者以某种方式过滤掉未填充的结果。


SO功能的代码如下。我注意到我已切换到cos(k),因为由于某种未知原因,我的计算机上rand()rand(1,1)之间的性能存在很大差异。但我认为这不会对结果产生太大影响。

function [] = SO()

    GATime  = timeit(@GrowAlways)
    DWNTime = timeit(@DoubleWhenNeeded)

end


function [] = DoubleWhenNeeded()

    A     = 0;
    sizeA = 1;
    for k = 1:1E5
        if ((k+1) > sizeA)
            A(2*sizeA) = 0;
            sizeA = 2*sizeA;
        end
        A(k+1) = cos(k);
    end

end

function [] = GrowAlways()

    A     = 0;
    for k = 1:1E5
        A(k+1) = cos(k);
    end

end