h5py não adere à especificação de fragmentação?

Problema: Eu tenho arquivos netCDF4 existentes (cerca de 5000 deles), (normalmente no formato 96x3712x3712), pontos de dados (float32). São arquivos com a primeira dimensão sendo hora (1 arquivo por dia), a segunda e a terceira dimensões espaciais. Atualmente, fazer uma fatia sobre a primeira dimensão (mesmo uma fatia parcial) levaria muito tempo devido aos seguintes motivos:

os arquivos netCDF são divididos em pedaços com um tamanho de pedaços de 1x3712x3712. Fatiar ao longo da dimensão do tempo basicamente leria o arquivo inteiro.o loop (mesmo em vários processos) em todos os arquivos menores também levaria muito tempo.

Meu gol:

criar arquivos mensais (cerca de 2900x3712x3712) pontos de dadosotimize-os para fatiar na dimensão do tempo (tamanho de 2900x1x1 ou um pouco maior nas dimensões espaciais)

Outros requerimentos:

os arquivos devem ser anexados por um único registro de data e hora (1x3712x3712) e esse processo de atualização deve levar menos de 15 minutosa consulta deve ser rápida o suficiente: uma fatia completa ao longo do tempo em menos de um segundo (ou seja, 2900x1x1) ==> na verdade, não há tantos dados ...de preferência, os arquivos devem estar acessíveis para leitura por vários processos enquanto estão sendo atualizadoso processamento dos dados históricos (os outros 5000 arquivos diários) deve levar menos de duas semanas, de preferência.

Já tentei várias abordagens:

concatenar os arquivos netcdf e recomeçá-los ==> leva muita memória e muito tempo ...escrevê-los de pandas para um arquivo hdf (usando pytables) ==> cria uma tabela ampla com um enorme índice. Isso também levará muito tempo para ler e exige que o conjunto de dados seja agrupado sobre as dimensões espaciais devido a restrições de metadados.minha última abordagem foi gravá-los em um arquivo hdf5 usando o h5py:

Aqui está o código para criar um único arquivo mensal:

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

Estou usando a última versão do HDF5 para ter a opção SWMR. O argumento fps é uma lista dos caminhos dos arquivos diários do netCDF4. Ele cria o arquivo (em um ssd, mas vejo que a criação do arquivo é principalmente vinculada à CPU) em cerca de 2 horas, o que é aceitável.

Eu tenho a compactação configurada para manter o tamanho do arquivo dentro dos limites. Eu fiz testes anteriores sem e vi que a criação sem é um pouco mais rápida, mas o fatiamento não demora muito mais com a compactação. O H5py agrupa automaticamente o conjunto de dados em blocos 1x116x116.

Agora, o problema: cortar em um NAS com configuração RAID 6 leva cerca de 20 segundos para cortar a dimensão do tempo, mesmo que esteja em um único pedaço ...

Eu acho que, mesmo que esteja em um único pedaço do arquivo, porque escrevi todos os valores em um loop, ele deve estar fragmentado de alguma forma (embora não saiba como esse processo funciona). É por isso que tentei fazer um h5repack usando as ferramentas CML do HDF5 em um novo arquivo, com os mesmos blocos, mas espero reordenando os valores para que a consulta possa ler os valores em uma ordem mais seqüencial, mas sem sorte. Embora esse processo tenha levado 6 horas para ser executado, não afetou a velocidade da consulta.

Se eu fizer meus cálculos corretamente, a leitura de um pedaço (2976x32x32) tem apenas alguns MB de tamanho (11 MB descompactados, acho que um pouco mais do que 1 MB compactado). Como isso pode demorar tanto? O que estou fazendo errado? Eu ficaria feliz se alguém pudesse lançar uma luz sobre o que realmente está acontecendo nos bastidores ...

questionAnswers(1)

yourAnswerToTheQuestion