ПРИМЕЧАНИЕ: Этот вопрос касается проблемы, замеченной еще в 2011 году со старой версией MATLAB (R2009a). Согласно приведенному ниже обновлению от июля 2016 года, проблема / ошибка в MATLAB, по-видимому, больше не существует (протестировано с R2016a; прокрутите вниз до конца вопроса, чтобы увидеть обновление).
Я использую MATLAB R2009b, и мне нужно написать больший скрипт, который преобразует содержимое большего набора .zip файлов в файлы v7.3 mat (с базовой моделью HDF5-datamodel). Чтение в порядке. Проблема с сохранением. И на самом деле нет проблем. Мои файлы хорошо сохраняются с помощью команды save .
Мой вопрос больше в том смысле: почему я наблюдаю следующее удивительное (для меня) поведение в MATLAB?
давайте посмотрим на мою проблему в целом. В этом текущем тестовом сценарии я буду генерировать один вывод: mat-файл -v7.3. Этот .mat-файл будет содержать 40 блоков в качестве отдельных переменных. Каждая переменная будет иметь имя «block_NNN» от 1 до 40 и будет содержать структуру с полями frames и 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;
Файл записан без проблем (286МБ). Выход:
Save data the simple way:
Elapsed time is 14.004449 seconds.
ОК - тогда я вспомнил, что хотел бы выполнить процедуру сохранения в течение 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 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
Файлы не идентичны по размеру. И тест с fc в Windows 7 показал ... ну много двоичных различий. Возможно, данные были немного смещены - таким образом, это ничего не говорит нам.
У кого-то есть идея, что здесь происходит? Возможно, в добавленном файле используется гораздо более оптимизированная структура данных? Или, может быть, Windows кэширует файл и делает доступ к нему намного быстрее?
Я также приложил усилия к тестовому чтению из двух файлов. Без представления цифр здесь добавленная версия была немного быстрее (хотя в долгосрочной перспективе это могло бы что-то значить).
[EDIT] : Я только что попытался использовать флаг отсутствия формата (по умолчанию -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.