hdf5: фрагментация увеличивает размер данных до 100%
В настоящее время я пишу скрипт на Python, чтобы объединить множество маленьких и не фрагментированных файлов.h5 (~7 МБ каждый). Общее дисковое пространство для всех файлов составляет несколько ГБ.
Каждый файл имеет два набора данных (тип uint8 и float32) с формой (строки, 11, 13, 18) и (строки, 6). Количество строк для каждого файла немного отличается (~ тысячи). Чтобы объединить файлы, мне нужно создать набор выходных данных по частям (maxshape).
Теперь я заметил, что полученный выходной файл занимает гораздо больше дискового пространства, чем для отдельных файлов, например, 7 МБ +7 МБ = 22 МБ.
Чтобы упростить проблему, можно также использовать n = 1 файлы для объединения, то есть преобразовать файл из не разделенного на части в файл.h5.
Если я вручную установлю небольшой размер фрагмента =2, результат будет 7 МБ (без чанковки) -> 7 МБ (с чанкованием).
Однако, если я увеличу размер фрагмента более чем на тысячу, требуемое дисковое пространство почти удвоится: 7 МБ (без чанковки) -> 14 МБ (с чанкованием).
Теперь я действительно задаюсь вопросом, почему такая большая разница между чанкированным и не чанкованным файлом.h5?
Вот выходные данные h5stat файлов chunksize=2 и chunksize=2500:
https://pastebin.com/Gg3LGQkk (2), https://pastebin.com/jUbfemp0 (2500).
Похоже, не метаданные, а сырые данные являются проблемой.
Является ли увеличенный размер диска нормальным для фрагментированного файла.h5? И если да, имеет ли смысл хранить мои данные с кусками? Позже я читаю большой конкатенированный файл.h5 строка за строкой, поэтому мне интересно, будет ли не разделенный на части файл.h5 (меньше по размеру диска) работать с вводом-выводом намного медленнее.
Фрагмент кода с реализацией h5py:
import h5py
#remove file_2 for the simplest non-chunked -> chunked conversion
file_list = [file_1.h5, file_2.h5] # not chunked, e.g. 2866 and 2825 rows
file_output = h5py.File('test.h5', 'w')
cum_rows_list = [0, 2866, 5691] # cumulative number of rows for the input
for n, input_file_name in enumerate(file_list):
print 'Processing file ' + file_list[n]
input_file = h5py.File(input_file_name, 'r')
for folder_name in input_file:
folder_data = input_file[folder_name]
if n == 0:
# first file; create the dummy dataset with no max shape
maxshape = (None,) + folder_data.shape[1:]
# create chunked output dataset
output_dataset = file_output.create_dataset(
folder_name, data=folder_data, maxshape=maxshape,
chunks=(2500,) + folder_data.shape[1:])
output_dataset.resize(cum_rows_list[-1], axis=0)
else:
# not important for only one file
...
file_output.flush()
file_output.close()
Обновление: как указал Яр в комментариях, разница в размере файла основана на заполнении из-за указанного размера фрагмента.