MATLAB: Enregistrer plusieurs variables à «-v7.3» (HDF5) .Mat-Files semble être plus rapide lors de l'utilisation du drapeau «-SEPEND». Comment venir?

StackOverflow https://stackoverflow.com/questions/4949939

Question

REMARQUE: Cette question traite d'un problème observé en 2011 avec une ancienne version MATLAB (R2009A). Selon la mise à jour ci-dessous de juillet 2016, le problème / bug de Matlab ne semble plus exister (testé avec R2016A; faites défiler vers le bas à la fin de la question pour voir la mise à jour).

J'utilise MATLAB R2009B et j'ai besoin d'écrire un script plus grand qui convertit le contenu d'un ensemble plus grand de fichiers .zip sur des fichiers MAT V7.3 (avec un Datamodel HDF5 sous-jacent). La lecture est OK. Le problème concerne l'épargne. Et il n'y a en fait aucun problème. Mes fichiers enregistrent bien en utilisant le enregistrer commande.

Ma question est plus dans le sens: pourquoi est-ce que je observe le comportement surprenant (pour moi) suivant dans Matlab?

Regardons mon problème en général. Dans cette sénario de test actuel, je générerai une sortie: A -v7.3 MAT-FILE. Ce mat-fichier contiendra 40 blocs comme variables individuelles. Chaque variable sera nommée "block_nnn" de 1 à 40 et contiendra une structure avec des champs cadres et blocage. Champ cadres Contient une séquence 480x240x65 d'Uint8 iMagedata (ici juste des données aléatoires générées en utilisant randi). Champ blocage contient le numéro de bloc.

Remarque: Dans le script réel (que je n'ai pas encore terminé), je ferai ce qui précède au total de 370 fois, convertissant un total de 108 Go de données brutes. C'est pourquoi je suis préoccupé par ce qui suit.

Quoi qu'il en soit, je définis d'abord quelques variables générales:

% some sizes for dummy data and loops:
num_blockCount = 40;
num_blockLength = 65;
num_frameHeight = 480;
num_frameWidth = 240;

Je génère ensuite un code factice qui a une forme et une taille identiques aux données brutes réelles:

% generate empty struct:
stu_data2disk = struct();

% loop over blocks:
for num_k = 1:num_blockCount

   % generate block-name:
   temp_str_blockName = sprintf('block_%03u', num_k);

   % generate temp struct for current block:
   temp_stu_value = struct();
   temp_stu_value.frames = randi( ...
      [0 255], ...
      [num_frameHeight num_frameWidth num_blockLength], ...
      'uint8' ...
   );
   temp_stu_value.blockNo = num_k;

   % using dynamic field names:
   stu_data2disk.(sprintf('block_%03u', num_k)) = temp_stu_value;

end

J'ai maintenant toutes mes données de test aléatoires dans une structure Stu_data2disk. Maintenant, je voudrais enregistrer les données en utilisant l'une des deux méthodes possibles.

Essayons d'abord le simple:

% save data (simple):
disp('Save data the simple way:')
tic;
save converted.mat -struct stu_data2disk -v7.3;
toc;

Le fichier est écrit sans problèmes (286 Mo). La sortie est:

Save data the simple way:
Elapsed time is 14.004449 seconds.

OK - alors je me suis souvenu que je voudrais suivre la procédure de sauvegarde sur les 40 blocs. Ainsi, au lieu de ce qui précède, je boucle sur les blocs et les ajoutez en séquence:

% save to file, using append:
disp('Save data using -append:')
tic;
for num_k = 1:num_blockCount

   % generate block-name:
   temp_str_blockName = sprintf('block_%03u', num_k);

   temp_str_appendToggle = '';
   if (num_k > 1)
      temp_str_appendToggle = '-append';
   end

   % generate save command:
   temp_str_saveCommand = [ ...
      'save ', ...
      'converted_append.mat ', ...
      '-struct stu_data2disk ', temp_str_blockName, ' '...
      temp_str_appendToggle, ' ', ...
      '-v7.3', ...
      ';' ...
   ];

   % evaluate save command:
   eval(temp_str_saveCommand);

end
toc;

Et encore une fois, le fichier enregistre bien (286 Mo). La sortie est:

Save data using -append:
Elapsed time is 0.956968 seconds.

Fait intéressant, la méthode de l'annexe est beaucoup plus rapide? Ma question est pourquoi?

Sortie de dir converted*.mat:

09-02-2011  20:38       300,236,392 converted.mat
09-02-2011  20:37       300,264,316 converted_append.mat
               2 File(s)    600,500,708 bytes

Les fichiers ne sont pas de taille identique. Et un test avec FC Dans Windows 7 a révélé ... enfin de nombreuses différences binaires. Peut-être que les données ont été un peu déplacées - donc cela ne nous dit rien.

Quelqu'un a-t-il une idée de ce qui se passe ici? Le fichier annexé utilise-t-il peut-être une structure de données beaucoup plus optimisée? Ou peut-être que Windows a mis en cache le fichier et y fait accès beaucoup plus rapidement?

J'ai également fait l'effort de lecture de test à partir des deux fichiers. Sans présenter les chiffres ici, la version annexée était un peu plus rapide (pourrait signifier quelque chose à long terme).

ÉDITER: J'ai juste essayé d'utiliser aucun drapeau de format (par défaut à -v7 sur mon système) et il n'y a plus beaucoup de différence:

Save data the simple way (-v7):
Elapsed time is 13.092084 seconds.
Save data using -append (-v7):
Elapsed time is 14.345314 seconds.

ÉDITER: J'ai corrigé l'erreur ci-dessus. Auparavant, j'ai mentionné que les statistiques étaient pour -v6 mais je me suis trompée. Je venais de supprimer l'indicateur de format et j'ai supposé que la valeur par défaut était -v6 mais en fait, il est -v7.

J'ai créé de nouvelles statistiques de test pour tous les formats de mon système en utilisant Fine Framework d'Andrew (tous les formats sont pour les mêmes données de test aléatoires, maintenant lues à partir de fichier):

15:15:51.422: Testing speed, format=-v6, R2009b on PCWIN, arch=x86, os=Microsoft Windows 7 Professional  6.1.7600 N/A Build 7600
15:16:00.829: Save the simple way:            0.358 sec
15:16:01.188: Save using multiple append:     7.432 sec
15:16:08.614: Save using one big append:      1.161 sec

15:16:24.659: Testing speed, format=-v7, R2009b on PCWIN, arch=x86, os=Microsoft Windows 7 Professional  6.1.7600 N/A Build 7600
15:16:33.442: Save the simple way:           12.884 sec
15:16:46.329: Save using multiple append:    14.442 sec
15:17:00.775: Save using one big append:     13.390 sec

15:17:31.579: Testing speed, format=-v7.3, R2009b on PCWIN, arch=x86, os=Microsoft Windows 7 Professional  6.1.7600 N/A Build 7600
15:17:40.690: Save the simple way:           13.751 sec
15:17:54.434: Save using multiple append:     3.970 sec
15:17:58.412: Save using one big append:      6.138 sec

Et les tailles des fichiers:

10-02-2011  15:16       299,528,768 converted_format-v6.mat
10-02-2011  15:16       299,528,768 converted_append_format-v6.mat
10-02-2011  15:16       299,528,832 converted_append_batch_format-v6.mat
10-02-2011  15:16       299,894,027 converted_format-v7.mat
10-02-2011  15:17       299,894,027 converted_append_format-v7.mat
10-02-2011  15:17       299,894,075 converted_append_batch_format-v7.mat
10-02-2011  15:17       300,236,392 converted_format-v7.3.mat
10-02-2011  15:17       300,264,316 converted_append_format-v7.3.mat
10-02-2011  15:18       300,101,800 converted_append_batch_format-v7.3.mat
               9 File(s)  2,698,871,005 bytes

Ainsi, -v6 semble être le plus rapide pour l'écriture. Pas non plus de grandes différences dans les tailles de fichiers. HDF5 a une méthode de base de base intégrée à ma connaissance.

Hmm, probablement une certaine optimisation dans les fonctions sous-jacentes de l'écriture HDF5?

Actuellement, je pense toujours que certaines fonctions de rédaction HDF5 fondamentale sous-jacentes sont optimisées pour l'ajout ensembles de données à un fichier HDF5 (ce qui se produit lors de l'ajout de nouvelles variables à un fichier -7.3). Je crois que j'ai lu quelque part que HDF5 devrait optimiser de cette manière ... mais je ne peux pas être sûr.

Autres détails à noter:

Le comportement est très systémique comme nous le voyons dans la réponse d'Andrew ci-dessous. Il semble également être très important de savoir si vous exécutez ou non ces choses dans une portée locale d'une fonction ou dans le "global" d'un M-Script. Mes premiers résultats provenaient d'un M-Script où les fichiers ont été écrits dans le répertoire actuel. Je ne peux encore reproduire que l'écriture d'une seconde pour -7,3 dans le M-Script. Les appels de fonction ajoutent apparemment des frais généraux.

Mise à jour en juillet 2016:

J'ai trouvé cela à nouveau et j'ai pensé que je pourrais le tester avec le plus récent Matlab à ma disposition en ce moment. Avec MATLAB R2016A sur Windows 7 X64, le problème semble avoir été résolu:

14:04:06.277: Testing speed, imax=255, R2016a on PCWIN64, arch=AMD64, 16 GB, os=Microsoft Windows 7 Enterprise  Version 6.1 (Build 7601: Service Pack 1)
14:04:10.600: basic -v7.3:                    7.599 sec      5.261 GB used
14:04:18.229: basic -v7.3:                    7.894 sec      5.383 GB used
14:04:26.154: basic -v7.3:                    7.909 sec      5.457 GB used
14:04:34.096: basic -v7.3:                    7.919 sec      5.498 GB used
14:04:42.048: basic -v7.3:                    7.886 sec      5.516 GB used     286 MB file   7.841 sec mean
14:04:50.581: multiappend -v7.3:              7.928 sec      5.819 GB used
14:04:58.544: multiappend -v7.3:              7.905 sec      5.834 GB used
14:05:06.485: multiappend -v7.3:              8.013 sec      5.844 GB used
14:05:14.542: multiappend -v7.3:              8.591 sec      5.860 GB used
14:05:23.168: multiappend -v7.3:              8.059 sec      5.868 GB used     286 MB file   8.099 sec mean
14:05:31.913: bigappend -v7.3:                7.727 sec      5.837 GB used
14:05:39.676: bigappend -v7.3:                7.740 sec      5.879 GB used
14:05:47.453: bigappend -v7.3:                7.645 sec      5.884 GB used
14:05:55.133: bigappend -v7.3:                7.656 sec      5.877 GB used
14:06:02.824: bigappend -v7.3:                7.963 sec      5.871 GB used     286 MB file   7.746 sec mean

Cela a été testé avec Andrew Janke reproMatfileAppendSpeedup Fonction dans la réponse acceptée ci-dessous (5 passes avec le format 7.3). À présent, -append est tout aussi lent ou plus lent, à une seule sauvegarde - comme il se doit. C'était peut-être un problème avec une construction précoce du pilote HDF5 utilisé dans R2009A.

Pas de solution correcte

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top