MATLAB: Сохранение нескольких переменных в «-v7.3» (HDF5) .mat-files кажется быстрее при использовании флага «-append». Почему?

ПРИМЕЧАНИЕ: Этот вопрос касается проблемы, наблюдаемой еще в 2011 году со старой версией MATLAB ( R2009a). Согласно приведенному ниже обновлению от июля 2016 г., проблема / ошибка в MATLAB, похоже, больше не существует (проверено с R2016a; прокрутите вниз до конца вопроса, чтобы увидеть обновление).

Я использую MATLAB R2009b, и мне нужно написать более крупный сценарий, который преобразует содержимое большего набора файлов .zip в файлы mat v7.3 (с базовой моделью данных HDF5). Чтение в порядке. Проблема с сохранением. И на самом деле проблем нет. Мои файлы хорошо сохраняются с помощью команды save .

Мой вопрос больше в том смысле: почему я наблюдаю следующее удивительное (для меня) поведение в MATLAB?

давайте рассмотрим мою проблему в Общее. В этом текущем тестовом сценарии я буду генерировать один вывод: -v7.3 mat-file. Этот .mat-файл будет содержать 40 блоков как отдельные переменные. Каждая переменная будет называться «block_NNN» от 1 до 40 и будет содержать структуру с полями , кадрами и blockNo . Поле frames содержит последовательность 480x240x65 изображений uint8 (здесь просто случайные данные, сгенерированные с использованием randi ). Поле blockNo содержит номер блока.

Примечание: В реальном скрипте (который мне еще предстоит закончить) я проделаю вышеописанное всего 370 раз, преобразование в общей сложности 108 ГБ необработанных данных. Вот почему меня беспокоит следующее.

В любом случае, сначала я определяю некоторые общие переменные:

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

Затем я генерирую некоторый фиктивный код, который имеет форму и размер, идентичные фактическим необработанным данным:

% 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

Теперь у меня есть все мои случайные тестовые данные в структуре stu_data2disk . Теперь я хотел бы сохранить данные одним из двух возможных методов.

Давайте сначала попробуем простой:

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

Файл записывается без проблем (286MB). Результат:

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

OK - тогда я вспомнил, что хотел бы выполнить процедуру сохранения для 40 блоков. Таким образом, вместо приведенного выше я перебираю блоки и добавляю их последовательно:

% 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;

И снова файл хорошо сохраняется (286 МБ). Результат:

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

Интересно, что метод добавления намного быстрее? У меня вопрос: почему?

Вывод из dir преобразован в * .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

Файлы не идентичны по размеру. И тест с fc в Windows 7 выявил ... ну, много двоичных различий. Возможно, данные были немного смещены - значит, это нам ничего не говорит.

Кто-нибудь имеет представление о том, что здесь происходит? Возможно, добавленный файл использует гораздо более оптимизированную структуру данных? Или, может быть, Windows кэширует файл и делает доступ к нему намного быстрее?

Я также попытался выполнить тестовое чтение из двух файлов. Без представления чисел добавленная версия была немного быстрее (хотя в конечном итоге может что-то значить).

Кто-нибудь знает, что здесь происходит? Возможно, добавленный файл использует гораздо более оптимизированную структуру данных? Или, может быть, Windows кэширует файл и делает доступ к нему намного быстрее?

Я также попытался выполнить тестовое чтение из двух файлов. Без представления чисел добавленная версия была немного быстрее (хотя в конечном итоге может что-то значить).

Кто-нибудь знает, что здесь происходит? Возможно, добавленный файл использует гораздо более оптимизированную структуру данных? Или, может быть, Windows кэширует файл и делает доступ к нему намного быстрее?

Я также попытался выполнить тестовое чтение из двух файлов. Без представления чисел добавленная версия была немного быстрее (хотя в конечном итоге может что-то значить).

[РЕДАКТИРОВАТЬ] : Я просто попытался использовать без флага формата (в моей системе по умолчанию -v7), и большой разницы больше нет:

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

[EDIT] : я исправил ошибку выше. Ранее я упоминал, что статистика была для -v6, но ошиблась. Я только что удалил флаг формата и предположил, что по умолчанию используется -v6, но на самом деле это -v7.

Я создал новую тестовую статистику для всех форматов в моей системе, используя прекрасную структуру Эндрю (все форматы предназначены для одних и тех же случайных тестовых данных. , теперь читаем из файла):

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

И размеры файлов:

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

Таким образом, -v6 кажется самым быстрым для записи. Также нет больших различий в размерах файлов. Насколько я знаю, HDF5 имеет встроенный базовый метод надувания.

Хмм, возможно, некоторая оптимизация в базовых функциях записи HDF5?

В настоящее время я все еще думаю, что некоторые базовые фундаментальные функции записи HDF5 оптимизированы для добавления наборов данных в файл HDF5 (что происходит при добавлении новых переменные в файл -7.3). Мне кажется, я где-то читал, что HDF5 следует оптимизировать именно таким образом ... хотя я не могу быть уверен.

Другие детали, на которые следует обратить внимание:

Поведение очень системное, как мы видим в ответе Эндрю ниже. Также кажется весьма важным, запускаете ли вы эти вещи в локальной области видимости функции или в «глобальной» области m-скрипта. Мои первые результаты были из m-скрипта, в котором файлы были записаны в текущий каталог. Я все еще могу воспроизвести только 1-секундную запись для -7.3 в m-скрипте. Очевидно, что вызовы функций добавляют некоторые накладные расходы.

Обновление, июль 2016 г. :

Я нашел это снова и подумал, что могу протестировать его с новейшей версией MATLAB, доступной мне на данный момент. В MATLAB R2016a в Windows 7 x64 проблема, похоже, была исправлена:

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

Это было протестировано с помощью функции reproMatfileAppendSpeedup Эндрю Янке в принятом ответе ниже (5 проходов с форматом 7.3). Теперь -append одинаково медленнее или медленнее для одного сохранения - как и должно быть. Возможно, это была проблема с ранней сборкой драйвера HDF5, используемого в R2009a.

11
задан Ole Thomsen Buus 15 July 2016 в 12:17
поделиться