Спасибо за ваши идеи.
ема: у меня есть существующие файлы netCDF4 (около 5000 из них), (обычно в форме 96x3712x3712) точек данных (float32). Это файлы с первым измерением времени (1 файл в день), вторым и третьим пространственными измерениями. В настоящее время создание среза по первому измерению (даже частичного среза) займет много времени по следующим причинам:
файлы netCDF разбиваются на куски размером 1x3712x3712. Нарезка по временному измерению в основном прочитала бы весь файл.зацикливание (даже в нескольких процессах) всех файлов меньшего размера также займет много времени.Моя цель:
создавать ежемесячные файлы (около 2900x3712x3712) точек данныхоптимизировать их для нарезки во временном измерении (размер фрагмента 2900x1x1 или немного больше в пространственных измерениях)Другие требования:
файлы должны быть добавлены с помощью одной отметки времени (1x3712x3712), и этот процесс обновления должен занимать менее 15 минутзапрос должен быть достаточно быстрым: полный срез со временем менее чем за одну секунду (то есть 2900x1x1) ==> не так много данных на самом деле ...предпочтительно файлы должны быть доступны для чтения несколькими процессами при обновленииобработка исторических данных (другие 5000 ежедневных файлов) должна занять не более пары недель.Я пробовал уже несколько подходов:
конкатенация файлов netcdf и их повторное разбиение ==> занимает слишком много памяти и слишком много времени ...запись их из панд в файл hdf (используя pytables) ==> создает широкую таблицу с огромным индексом. Это в конечном итоге потребует слишком много времени для чтения и потребует разбиения набора данных на пространственные измерения из-за ограничений метаданных.мой последний подход был записать их в файл hdf5, используя h5py:Вот код для создания одного ежемесячного файла:
import h5py
import pandas as pd
import numpy as np
def create_h5(fps):
timestamps=pd.date_range("20050101",periods=31*96,freq='15T') #Reference time period
output_fp = r'/data/test.h5'
try:
f = h5py.File(output_fp, 'a',libver='latest')
shape = 96*nodays, 3712, 3712
d = f.create_dataset('variable', shape=(1,3712,3712), maxshape=(None,3712,3712),dtype='f', compression='gzip', compression_opts=9,chunks=(1,29,29))
f.swmr_mode = True
for fp in fps:
try:
nc=Dataset(fp)
times = num2date(nc.variables['time'][:], nc.variables['time'].units)
indices=np.searchsorted(timestamps, times)
for j,time in enumerate(times):
logger.debug("File: {}, timestamp: {:%Y%m%d %H:%M}, pos: {}, new_pos: {}".format(os.path.basename(fp),time,j,indices[j]))
d.resize((indices[j]+1,shape[1],shape[2]))
d[indices[j]]=nc.variables['variable'][j:j+1]
f.flush()
finally:
nc.close()
finally:
f.close()
return output_fp
Я использую последнюю версию HDF5, чтобы иметь опцию SWMR. Аргумент fps представляет собой список путей к файлам ежедневных файлов netCDF4. Он создает файл (на ssd, но я вижу, что создание файла в основном связано с процессором) примерно за 2 часа, что приемлемо.
У меня настроено сжатие, чтобы размер файла не выходил за пределы. Я провёл более ранние тесты без и увидел, что создание без немного быстрее, но срезание занимает не так много времени со сжатием. H5py автоматически разбивает набор данных на куски 1x116x116.
Теперь проблема: нарезка на NAS с настройкой RAID 6 занимает около 20 секунд, чтобы разрезать измерение времени, даже если оно находится в одном фрагменте ...
Я полагаю, что, хотя он и находится в одном фрагменте файла, поскольку я записал все значения в цикле, он должен быть как-то фрагментирован (хотя не знаю, как работает этот процесс). Вот почему я попытался сделать h5repack с использованием инструментов CML из HDF5 в новый файл, с теми же кусками, но, надеюсь, переупорядочив значения, чтобы запрос мог читать значения в более последовательном порядке, но безуспешно. Несмотря на то, что этот процесс занял 6 часов, он никак не влиял на скорость запроса.
Если я правильно делаю свои вычисления, чтение одного фрагмента (2976x32x32) занимает всего несколько МБ (11 МБ без сжатия, я думаю, что сжато чуть больше 1 МБ). Как это может занять так много времени? Что я делаю неправильно? Я был бы рад, если бы кто-то мог пролить свет на то, что на самом деле происходит за кулисами ...