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