【问题标题】:Preallocation of cell array in matlabmatlab中单元格数组的预分配
【发布时间】:2013-07-25 04:25:10
【问题描述】:

这更像是一个理解行为而不是具体问题的问题。

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 中为异构数据创建一个数据容器(预分配是不可能的,因为一开始不知道最终大小)。我认为句柄类不好,因为它们也有巨大的开销。

已经期待学习一些东西

magu_

编辑: 我尝试了 Eitan T 提出的链表,但我认为 matlab 的开销仍然很大。我尝试使用双数组作为数据 (rand(200000,1))。

我做了一个小情节来说明:

图表代码:(我使用了 matlab 主页中的 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'})

不要误会我喜欢链表的想法,因为它相当灵活,但我认为开销可能很大。

【问题讨论】:

    标签: matlab memory cell


    【解决方案1】:

    元胞数组是否类似于 C++ 中的向量或指针数组?

    元胞数组确实允许存储不同类型和大小的数据,但每个元胞还会增加 112 字节的固定开销(请参阅this other answer of mine)。这远远超过 8 字节双精度,这是不可忽略的,尤其是在处理您的示例中的大型元胞数组时。

    可以合理地假设一个单元格数组被实现为一个连续的指针数组,每个指针指向单元格的实际内容。

    这意味着您可以单独修改每个单元格的内容,而无需实际调整单元格数组容器本身的大小。但是,这也意味着向元胞数组添加新元胞需要动态存储分配,这就是为元胞数组预分配内存可以提高性能的原因。

    一个相关的问题是,如果我想在 Matlab 中为异构数据创建一个数据容器(预分配是不可能的,因为一开始不知道最终大小)

    不知道最终大小确实可能是个问题,但您始终可以预先分配一个具有所需最大支持大小的单元格数组(如果有的话),并在最后删除空单元格。我还建议您查看implementing linked lists in MATLAB

    【讨论】:

    • 感谢您的回答。即使单元阵列大 1.5 倍,这仍然不能解释所需的大量额外时间。我还检查了链表的东西。我相应地更新了我的问题
    • @magu_ 单元格数组不是大 1.5 倍,而是大 14 (=112/8) 倍,如果每个数值存储在不同的单元格中。这是相当重要的。用某个最大大小预分配单元阵列怎么样?关于链接列表,您可以发布您的代码以便对其进行审核吗?
    • 对,右字节不是位。这当然有很大的不同。嗯,这可能是造成差异的原因
    猜你喜欢
    • 2012-12-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-07
    • 1970-01-01
    • 2016-12-01
    • 1970-01-01
    • 2016-08-30
    相关资源
    最近更新 更多