这更像是一个理解行为而不是具体问题的问题。
Mathworks指出数值是连续存储的,这使得预分配很重要。元胞数组不是这种情况。
它们是否类似于 C++ 中的向量或指针数组?
这意味着预分配并不那么重要,因为指针的大小是 double 的一半(根据 whos - 但在某处存储 mxArray 的数据类型肯定会有开销)。
运行此代码:
clear all
n = 1e6;
tic
A = [];
for i=1:n
A(end + 1) = 1;
end
fprintf('Numerical without preallocation %f s\n',toc)
clear A
tic
A = zeros(1,n);
for i=1:n
A(i) = 1;
end
fprintf('Numerical with preallocation %f s\n',toc)
clear A
tic
A = cell(0);
for i=1:n
A{end + 1} = 1;
end
fprintf('Cell without preallocation %f s\n',toc)
tic
A = cell(1,n);
for i=1:n
A{i} = 1;
end
fprintf('Cell with preallocation %f s\n',toc)
返回: 无预分配的数值 0.429240 s 有预分配的数值 0.025236 s 无预分配的单元 4.960297 s 有预分配的单元 0.554257 s
数值并不奇怪。但是这确实让我感到惊讶,因为只有指针的容器而不是数据本身需要重新分配。这应该(因为指针小于双精度)导致<.2s的差异。这个开销从何而来?
一个相关的问题是,如果我想在 Matlab 中为异构数据创建一个数据容器(预分配是不可能的,因为一开始不知道最终大小)。我认为句柄类不好,因为它们也有巨大的开销。
已经期待学习一些东西
马古_
编辑: 我尝试了 Eitan T 提出的链表,但我认为 matlab 的开销仍然很大。我尝试使用双数组作为数据(rand(200000,1))。
我做了一个小情节来说明:
图表代码:(我使用了 matlab hompage 中的 dlnode 类,如回答帖子中所述)
D = 兰德(200000,1);
s = linspace(10,20000,50);
nC = zeros(50,1);
nL = zeros(50,1);
for i = 1:50
a = cell(0);
tic
for ii = 1:s(i)
a{end + 1} = D;
end
nC(i) = toc;
a = list([]);
tic
for ii = 1:s(i)
a.insertAfter(list(D));
end
nL(i) = toc;
end
figure
plot(s,nC,'r',s,nL,'g')
xlabel('#iter')
ylabel('time (s)')
legend({'cell' 'list'})
不要误会我的意思,我喜欢链表的想法,因为它相当灵活,但我认为开销可能很大。