web-dev-qa-db-fra.com

Comment initialiser un tableau de structures dans MATLAB?

Comment puis-je préallouer un tableau de structures dans MATLAB? Je veux préallouer "a" dans cet exemple afin qu'il ne redimensionne pas plusieurs fois.

a = []
for i = 1:100
  a(i).x = i;
end
44
Mohammad Moghimi

L'utilisation de repmat est de loin le moyen le plus efficace de préallouer des structures:

N = 10000;    
b = repmat(struct('x',1), N, 1 );

C'est ~ 10x plus rapide en utilisant Matlab 2011a que la pré-allocation via l'indexation, comme dans

N      = 10000;
b(N).x = 1

La méthode d'indexation n'est que légèrement plus rapide que la préallocation.

No preallocation:            0.075524    
Preallocate Using indexing:  0.063774
Preallocate with repmat:     0.005234


Code ci-dessous au cas où vous voudriez vérifier.

        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)])

Résultats dans la fenêtre de commande:

No preallocation:        0.075524    
Preallocate Indexing:    0.063774
Preallocate with repmat: 0.0052338
>> 

P.S. J'aimerais savoir pourquoi c'est vrai, si quelqu'un peut l'expliquer.

72
jerad

Il y a une belle discussion à ce sujet dans Loren on the Art of MATLAB blog.

Si je vous comprends bien, voici quelques façons d'initialiser la structure que vous souhaitez:

a(100).x = 100;

Avec cette méthode, nous pouvons voir que les éléments sont remplis avec des tableaux vides.

11
bla

Il existe de nombreuses façons d'initialiser une structure. Par exemple, vous pouvez utiliser la commande struct:

a(1:100) = struct('x',[]);

qui met tous les champs x à vide.

Vous pouvez également utiliser deal pour créer et remplir la structure si vous savez quelles données doivent y entrer

xx = num2cell(1:100);
[a(1:100).x]=deal(xx{:});
a(99).x
ans =
    99

Ou vous pouvez utiliser à nouveau struct (notez que si un champ de la structure doit être un tableau de cellules, la cellule doit être placée entre crochets!)

a = struct('x',xx)
11
Jonas

La façon dont cela est censé être fait, et la plus simple est

a=struct('x',cell(1,N));

Si vous corrigez le "tic" manquant et ajoutez cette méthode au code de benchmarking présenté par jerad, la méthode que je propose ci-dessus est un peu plus lente que repmat mais beaucoup plus simple à implémenter, voici la sortie:

No preallocation:        0.10137
Preallocate Indexing:    0.07615
Preallocate with repmat: 0.01458
Preallocate with struct: 0.07588

La raison pour laquelle repmat est plus rapide est qu'une valeur est attribuée à chaque champ "x" lors de la pré-allocation, au lieu de la laisser vide. Si la technique de pré-allocation ci-dessus est modifiée, nous commençons avec tous les champs x avec une valeur (un) attribuée, comme ceci:

    a=cell(1,N);
    a(:)={1};
    d=struct('x',a);

Ensuite, le benchmarking s'améliore beaucoup, a été très proche ou plus rapidement que repmat. La différence est si petite que chaque fois que je l'exécute, elle change laquelle est la plus rapide. Voici un exemple de sortie:

No preallocation:        0.0962
Preallocate Indexing:    0.0745
Preallocate with repmat: 0.0259
Preallocate with struct: 0.0184

Inversement, si la pré-allocation repmat est modifiée pour que le champ soit vide, comme ceci

b = repmat( struct( 'x', {} ), N, 1 );

Tout l'avantage de vitesse est perdu

1
Camilo Rada