如何在MATLAB中预分配结构数组?我想在此示例中预先分配“a”,以便它不会多次调整大小。
a = []
for i = 1:100
a(i).x = i;
end
答案 0 :(得分:71)
使用repmat
是迄今为止预分配结构的最有效方法:
N = 10000;
b = repmat(struct('x',1), N, 1 );
使用Matlab 2011a比使用索引预先分配快~~ 10倍,如
N = 10000;
b(N).x = 1
索引方法仅比未预先分配的方法快一点。
No preallocation: 0.075524
Preallocate Using indexing: 0.063774
Preallocate with repmat: 0.005234
以下代码,以便您进行验证。
clear;
N = 10000;
%1) GROWING A STRUCT
tic;
for ii=1:N
a(ii).x(1)=1;
end
noPreAll = toc;
%2)PREALLOCATING A STRUCT
tic;
b = repmat( struct( 'x', 1 ), N, 1 );
for ii=1:N
b(ii).x(1)=1;
end;
repmatBased=toc;
%3)Index to preallocate
tic;
c(N).x = 1;
for ii=1:N
c(ii).x(1)=1;
end;
preIndex=toc;
disp(['No preallocation: ' num2str(noPreAll)])
disp(['Preallocate Indexing: ' num2str(preIndex)])
disp(['Preallocate with repmat: ' num2str(repmatBased)])
命令窗口中的结果:
No preallocation: 0.075524
Preallocate Indexing: 0.063774
Preallocate with repmat: 0.0052338
>>
P.S。如果有人能解释的话,我有兴趣知道为什么会这样。
答案 1 :(得分:11)
在Loren on the Art of MATLAB博客中对此进行了很好的讨论。
如果我理解正确,这里有一种初始化所需结构的方法:
a(100).x = 100;
使用这种方法,我们可以看到元素用空数组填充。
答案 2 :(得分:11)
您可以通过多种方式初始化结构。例如,您可以使用struct
命令:
a(1:100) = struct('x',[]);
将所有字段x
设置为空。
如果您知道哪些数据应该在那里,您还可以使用deal
来创建和填充结构
xx = num2cell(1:100);
[a(1:100).x]=deal(xx{:});
a(99).x
ans =
99
或者您可以再次使用struct
(请注意,如果结构的字段应该是单元格数组,则需要将单元格括在大括号中!)
a = struct('x',xx)
答案 3 :(得分:1)
应该这样做的方式,最简单的是
a=struct('x',cell(1,N));
如果你修复了缺失的" tic"并将此方法添加到jerad提供的基准测试代码中,我上面提出的方法比repmat慢一点但实现起来要简单得多,这里是输出:
No preallocation: 0.10137
Preallocate Indexing: 0.07615
Preallocate with repmat: 0.01458
Preallocate with struct: 0.07588
repmat更快的原因是因为每个' x'字段在预分配期间分配,而不是将其留空。如果更改了上述预分配技术,那么我们从分配了值(一)的所有x字段开始,如下所示:
a=cell(1,N);
a(:)={1};
d=struct('x',a);
然后,基准测试改进很多,非常接近或比repmat快一些。差异是如此之小,以至于每次运行它都会改变哪一个更快。这是一个输出示例:
No preallocation: 0.0962
Preallocate Indexing: 0.0745
Preallocate with repmat: 0.0259
Preallocate with struct: 0.0184
相反,如果更改了repmat预分配以将字段设置为空,就像这样
b = repmat( struct( 'x', {} ), N, 1 );
失去了所有的速度优势
答案 4 :(得分:0)
使用 cell2struct 是迄今为止我能想到的最快的方法。只需检查以下代码即可进行比较:
clear;
N = 10000;
cel2s=0;
repm=0;
for i=1:100
a=0.0; b=0.0;
tic;
a = cell2struct(cell(1,N), {'x'}, 1 );
cel2s = cel2s + toc;
tic;
b = repmat(struct('x',1), N, 1 );
repm = repm + toc;
end
disp(['cell2struct preallocation: ', num2str(cel2s/100)]);
disp(['repmat preallocation : ', num2str(repm/100)]);
disp(['speedup : ', num2str(fix( repm/cel2s ) ) , ' X']);
典型结果显示平均加速约 19 倍!与 repmat 方法相比:
cell2struct preallocation: 1.4636e-05
repmat preallocation : 0.00028794
speedup : 19 X
答案 5 :(得分:-1)
根据this answer,还有另一种方法:
[a.x] = deal(val);
其中val
是您要分配给结构的每个元素的值。
此命令的效果与其他命令的效果不同,因为每个结构x
的每个a
字段都将分配val
值。
答案 6 :(得分:-1)
不是预先分配结构数组,而是可以更容易地反转循环。通过这种方式,数组在第一次迭代中分配,其余的迭代用于填充结构。
a = []
for i = 100:-1:1
a(i).x = i;
end