51

MATLABで構造体の配列を事前に割り当てるにはどうすればよいですか?この例では、サイズが何度も変更されないように「a」を事前に割り当てたいと思います。

a = []
for i = 1:100
  a(i).x = i;
end
4

7 に答える 7

80

使用する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
>> 

PS 誰かがそれを説明できれば、なぜこれが真実なのか知りたいです。

于 2012-12-01T22:40:28.860 に答える
11

これについては、ArtofMATLABブログのLorenで素晴らしい議論があります。

私があなたを正しく理解しているなら、あなたが望む構造体を初期化する方法はここにあります:

a(100).x = 100;

この方法では、要素が空の配列で埋められていることがわかります。

于 2012-12-01T22:12:12.820 に答える
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)
于 2012-12-01T22:47:18.033 に答える
3

これが行われることになっている方法、そして最も簡単なのは

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」フィールドの値が、空のままにするのではなく、事前割り当て中に割り当てられるためです。上記の事前割り当て手法が変更された場合は、次のように、値(1)が割り当てられたすべての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 );

すべての速度の利点が失われます

于 2018-03-07T20:54:21.370 に答える
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倍のスピードアップを示しています。wrt repmatメソッド:

cell2struct preallocation: 1.4636e-05
repmat preallocation     : 0.00028794
speedup                  : 19 X
于 2021-06-11T08:32:30.573 に答える
-1

この回答によると、それを行う別の方法もあります:

[a.x] = deal(val);

ここで、は構造体のすべてvalの要素に割り当てる値です。

このコマンドの効果は、xすべての構造のすべてのフィールドに値aが割り当てられるため、他のコマンドの効果とは異なりvalます。

于 2015-06-24T16:39:47.473 に答える
-1

構造体の配列を事前に割り当てる代わりに、ループを逆にする方が簡単な場合があります。このようにして、配列は最初の反復で割り当てられ、残りの反復は構造体を埋めるために使用されます。

a = []
for i = 100:-1:1
    a(i).x = i;
end
于 2015-07-13T15:51:47.263 に答える