Проблема переименования всех наборов данных HDF5 в группе для больших файлов hdf5 - PullRequest
0 голосов
/ 31 октября 2018

У меня проблема с переименованием наборов данных в hdf5. Процесс крайне медленный. Я прочитал некоторую документацию, в которой говорится, что имена наборов данных - это просто ссылки на данные, поэтому приемлемый способ переименования:

group['new_name'] = group['old_name']
del group['old_name']

Но это так медленно (всего 5% завершено за ночь), и это заставляет меня думать, что мой процесс совершенно неправильный.

Я использую Python h5py, и вот мой медленный код:

# Open file
with h5py.File('test.hdf5') as f:

    # Get all top level groups
    top_keys = [key for key in f.keys()]

    # Iterate over each group
    for top_key in top_keys:
        group = f[top_key]
        tot_digits = len(group)

        #Rename all datasets in the group (pad with zeros)
        for key in tqdm(group.keys()):
            new_key = str(key)
            while len(new_key)<tot_digits:
                new_key = '0'+str(new_key)
            group[new_key] = group[key]
            del group[key]

В соответствии с предложением @jpp я также попытался заменить последние две строки на group.move:

group.move(key, new_key)

Но этот метод был одинаково медленным. У меня есть несколько групп с одинаковым количеством наборов данных, но у каждой группы есть наборы данных разного размера. Группа с самыми большими наборами данных (большинство байтов), кажется, переименовывает самую медленную.

Конечно, есть способ сделать это быстро. Является ли имя набора данных просто символической ссылкой? Или переименование по своей сути вызывает переписывание всего набора данных? Как мне переименовать множество наборов данных в файле HDF5?

Ответы [ 2 ]

0 голосов
/ 11 ноября 2018

Как насчет этого? Может ли быть так, что поиск группы занимает больше времени, чем простая итерация? Я сделал несколько оптимизаций - поскольку у меня нет тестового файла, я не могу его опробовать.

# Open file
with h5py.File('test.hdf5') as f:

    # Iterate over each group
    for top_key, group in f.items():
        #Rename all datasets in the group (pad with zeros)
        for key in tqdm(group.keys()):
            new_key = ("{:0<" + str(len(group)) + "}").format(str(key))
            group.move(key, new_key)
0 голосов
/ 08 ноября 2018

Один из возможных виновников, по крайней мере, если у вас под клавишами верхнего уровня большое количество групп, - это то, что вы создаете новое имя очень неэффективным способом. Вместо

while len(new_key)<tot_digits:
    new_key = '0'+str(new_key)

Вы должны сгенерировать новый ключ следующим образом:

if len(new_key)<tot_digits:
    new_key = (tot_digits-len(new_key))*'0' + new_key

Таким образом, вы не создаете новый строковый объект для каждой дополнительной цифры, которую нужно добавить.

Также возможно, хотя я не могу этого подтвердить, что вызов group.keys() вернет итератор, который будет заполнен новыми именами ключей, которые вы добавляете, так как вы изменяете группу, перебирая ключи. Стандартный итератор Python выдает RuntimeError, но ясно, что hf5py сделает то же самое. Чтобы убедиться, что у вас нет этой проблемы, вы можете просто создать список ключей заранее.

for key in tqdm(list(group.keys())):
...