这是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;
第二种方法具有与行和列阵列兼容的明显优势。
然而,这个问题是:这两种方法中哪一种最快?我的直觉告诉我第二种方法是,但我想要一些证据支持或反对。有什么想法吗?
答案 0 :(得分:4)
A(end+1) = elem
)更快根据以下基准(使用timeit
benchmarking function from File Exchange运行),第二种方法(A(end+1) = elem
)更快,因此应该首选。
有趣的是,尽管如此,两种方法之间的性能差距在旧版MATLAB中要比在最新版本中差得多。
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