Спасибо за ваши идеи.

ема: у меня есть существующие файлы 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 МБ). Как это может занять так много времени? Что я делаю неправильно? Я был бы рад, если бы кто-то мог пролить свет на то, что на самом деле происходит за кулисами ...

Ответы на вопрос(1)

Ваш ответ на вопрос