У нас проблема в том, что нам нужно сохранить временный кадр данных из ~ 10 столбцов смешанных данных (float / int) на диске, а затем прочитать и обработать его впоследствии.
Кадр данных реальной ситуации будет ~> 300 миллионов строк, что приводит к сжатому hdf-файлу размером 10 ГБ +, поэтому мы не можем позволить себе читать все это в памяти и обрабатывать его по частям.
По нашему опыту - запись в hdf с использованием панд выполняется быстро:
chunks = map(job, range(num_chunks))
append = False
for chunk in chunks:
chunk.to_hdf(output,
key='results',
format='table',
complevel=9,
complib="blosc:snappy",
append=append)
append = True
, где job
- это функция, которая возвращает фрагмент данных.В реальной ситуации мы генерируем порции, используя multiprocessing
, но это не имеет никакого отношения к проблеме ...
Однако чтение занимает слишком много времени - кажется, даже неадекватным - я уверен, что я делаю что-то не тактам:
res = pd.read_hdf(output,key='results',iterator=True,chunksize=chunksize_read)
## Do some silly computation on each chunk here
## real-life processing is going to be some histogramming
compute_res = [ _['a'].mean() for _ in res ]
Некоторые моменты реального времени - ~ 2 минуты для генерации ~ 10 ГБ hdf и ~ 40 + минут (!!!) для чтения полученного файла ...
Проблемакажется, не связаны со смешанными типами данных в кадре данных ... Я создал супер-минимальный пример , где я могу воспроизвести ту же проблему с кадром данных всего в 1 столбце с плавающей запятой (!).
Вот некоторые примеры использования этого минимального примера:
time took to write 50000000 elements in 100 chunks to xxx.h5: 15.09 sec
time took to read 50000000 elements in chunks of 100 and to do a mock computation per chunk: 322.29 sec
time took to read 50000000 elements in RAM at once and to do a mock computation: 0.87 sec
Любая помощь приветствуется!Спасибо!
PS
Нам даже не нужно использовать hdf
для этого ... Но мы бы очень хотели сохранить его в pandas
API - то есть dataframe_chunk.to_whatever(fname,some_nice_compression=True)
с одной стороны и for chunk in pandas.from_whatever(fname,iterator=True ...): do_stuff(chunk)
с другой стороны.