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