У меня есть несколько больших файлов HDF5, хранящихся на SSD (размер сжатого файла lzf составляет 10–15 ГБ, размер несжатого файла - 20–25 ГБ). Чтение содержимого такого файла в оперативную память для дальнейшей обработки занимает примерно 2 минуты на файл. За это время используется только одно ядро (но до 100%). Таким образом, я предполагаю, что декомпрессионная часть, работающая на CPU, является узким местом, а не пропускной способностью ввода-вывода SSD.
В начале моей программы она считывает несколько файлов такого рода в оперативную память, что занимает довольно много времени.
Мне нравится ускорять этот процесс, используя больше ядер и, в конечном итоге, больше оперативной памяти, пока пропускная способность ввода-вывода SSD не станет ограничивающим фактором. Машина, на которой я работаю, имеет много ресурсов (20 процессорных ядер [+ 20 HT] и 400 ГБ ОЗУ), и «потеря» ОЗУ не представляет особой проблемы, если она оправдана экономией времени.
У меня было две идеи:
1) Используйте модуль Python multiprocessing
для чтения нескольких файлов в ОЗУ параллельно. Это работает в принципе, но из-за использования Pickle в multiprocessing
(как указано здесь ), я достиг предела сериализации 4 ГБ:
OverflowError ('не может сериализовать объект байтов размером более 4 ГиБ').
2) Сделайте несколько процессов (используя Pool
из модуля multiprocessing
), откройте один и тот же файл HDF5 (используя with h5py.File('foo.h5', 'r') as h_file:
), прочитайте отдельный фрагмент из него (chunk = h_file['label'][i : i + chunk_size]
) и верните этот фрагмент. Собранные куски будут затем объединены. Однако это не удается с
OSError: Невозможно прочитать данные (ошибка данных обнаружена контрольной суммой Fletcher32).
Это связано с тем, что я открываю один и тот же файл в нескольких процессах (как предложено здесь )?
Итак, мой последний вопрос: как я могу быстрее прочитать содержимое файлов .h5
в основную память? Опять же: «Тратить» ОЗУ в пользу экономии времени разрешено. Содержимое должно находиться в основной памяти, поэтому обойти проблему, просто прочитав строки или дроби, не вариант.
Я знаю, что могу просто хранить файлы .h5
без сжатия, но это только последний вариант, который мне нравится использовать, поскольку места на SSD недостаточно. Я предпочитаю как сжатые файлы, так и быстрое чтение (в идеале лучше использовать имеющиеся ресурсы).
Мета-информация: я использую python 3.5.2 и h5py 2.8.0.
EDIT: при чтении файла SSD работает со скоростью 72 МБ / с, что далеко от максимума. Файлы .h5
были созданы с использованием метода create_dataset
h5py с опцией compression="lzf"
.
РЕДАКТИРОВАТЬ 2: Это (упрощенный) код, который я использую для чтения содержимого (сжатого) файла HDF5:
def opener(filename, label): # regular version
with h5py.File(filename, 'r') as h_file:
data = g_file[label][:]
return data
def fast_opener(filename, label): # multiple processes version
with h5py.File(filename, 'r') as h_file:
length = len(h_file[label])
pool = Pool() # multiprocessing.Pool and not multiprocessing.dummy.Pool
args_iter = zip(
range(0, length, 1000),
repeat(filename),
repeat(label),
)
chunks = pool.starmap(_read_chunk_at, args_iter)
pool.close()
pool.join()
return np.concatenate(chunks)
def _read_chunk_at(index, filename, label):
with h5py.File(filename, 'r') as h_file:
data = h_file[label][index : index + 1000]
return data
Как видите, декомпрессия выполняется прозрачно с помощью h5py.