Проблемы ввода-вывода при загрузке нескольких больших файлов H5PY (Pytorch)

0

Вопрос

Я столкнулся с проблемой!

Недавно я столкнулся с проблемой ввода-вывода. Целевые и входные данные хранятся в файлах h5py. Каждый целевой файл составляет 2,6 ГБ, а каждый входной файл-10,2 ГБ. У меня есть 5 входных наборов данных и в общей сложности 5 целевых наборов данных.

Я создал пользовательскую функцию набора данных для каждого файла h5py, а затем использовал данные.Класс ConcatDataset для связи всех наборов данных. Функция пользовательского набора данных является:

class MydataSet(Dataset):
def __init__(self, indx=1, root_path='./xxx', tar_size=128, data_aug=True, train=True):
    self.train = train
    if self.train:
        self.in_file = pth.join(root_path, 'train', 'train_noisy_%d.h5' % indx)
        self.tar_file = pth.join(root_path, 'train', 'train_clean_%d.h5' % indx)
    else:
        self.in_file = pth.join(root_path, 'test', 'test_noisy.h5')
        self.tar_file = pth.join(root_path, 'test', 'test_clean.h5')
    self.h5f_n = h5py.File(self.in_file, 'r', driver='core')
    self.h5f_c = h5py.File(self.tar_file, 'r')
    self.keys_n = list(self.h5f_n.keys())
    self.keys_c = list(self.h5f_c.keys())
    # h5f_n.close()
    # h5f_c.close()

    self.tar_size = tar_size
    self.data_aug = data_aug

def __len__(self):
    return len(self.keys_n)

def __del__(self):
    self.h5f_n.close()
    self.h5f_c.close()

def __getitem__(self, index):
    keyn = self.keys_n[index]
    keyc = self.keys_c[index]
    datan = np.array(self.h5f_n[keyn])
    datac = np.array(self.h5f_c[keyc])
    datan_tensor = torch.from_numpy(datan).unsqueeze(0)
    datac_tensor = torch.from_numpy(datac)
    if self.data_aug and np.random.randint(2, size=1)[0] == 1: # horizontal flip
        datan_tensor = torch.flip(datan_tensor,dims=[2]) # c h w
        datac_tensor = torch.flip(datac_tensor,dims=[2])

Затем я использую dataset_train = data.ConcatDataset([MydataSet(indx=index, train=True) for index in range(1, 6)]) для тренировок. Когда используются только 2-3 файла h5py, скорость ввода-вывода нормальная, и все идет правильно. Однако при использовании 5 файлов скорость обучения постепенно уменьшается (от 5 итераций/с до 1 итерации/с). Я меняю num_worker, и проблема все еще существует.

Кто-нибудь может подсказать мне решение? Должен ли я объединить несколько файлов h5py в один больший? Или другими методами? Заранее спасибо!

h5py python pytorch pytorch-dataloader
2021-11-24 02:02:17
1

Лучший ответ

1

Повышение производительности требует временных ориентиров. Для этого вам необходимо определить потенциальные узкие места и связанные с ними сценарии. Вы сказали "с 2-3 файлами скорость ввода-вывода нормальная" и "при использовании 5 файлов скорость обучения постепенно снижается". Итак, ваша проблема со скоростью ввода-вывода связана с производительностью или скоростью обучения? Или ты знаешь? Если вы не знаете, вам нужно изолировать и сравнить производительность ввода-вывода и производительность обучения отдельно для 2 сценариев.
Другими словами, для измерения производительности ввода-вывода (только) вам необходимо выполнить следующие тесты:

  1. Время для чтения и объединения 2-3 файлов,
  2. Время для чтения и объединения 5 файлов,
  3. Скопируйте 5 файлов в 1 и засеките время чтения из объединенного файла,
  4. Или свяжите 5 файлов с 1 файлом и временем.

И для измерения скорости обучения (только) вам необходимо сравнить производительность для следующих тестов:

  • Объедините 2-3 файла, затем прочитайте и обучите из объединенного файла.
  • Объедините все 5 файлов, затем прочитайте и обучите из объединенного файла.
  • Или свяжите 5 файлов с 1 файлом, а затем прочитайте и обучитесь из связанного файла.

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

Ниже приведен код, который показывает оба метода. Подставьте свои имена файлов в fnames список, и он должен быть готов к запуску. Если имена ваших наборов данных не уникальны, вам нужно будет создать уникальные имена и назначить в h5fr.copy() -- вот так: h5fr.copy(h5fr[ds],h5fw,'unique_dataset_name')

Код для объединения или связывания файлов :
(прокомментируйте/раскомментируйте строки по мере необходимости)

import h5py
fnames = ['file_1.h5','file_2.h5','file_3.h5']
# consider changing filename to 'linked_' when using links:
with h5py.File(f'merge_{len(fnames)}.h5','w') as h5fw:      
    for fname in fnames:
        with h5py.File(fname,'r') as h5fr:
            for ds in h5fr.keys():
                # To copy datasets into 1 file use:
                h5fr.copy(h5fr[ds],h5fw)
                # to link datasets to 1 file use:
                # h5fw[ds] = h5py.ExternalLink(fname,ds)
2021-11-25 15:23:04

После публикации кода, который копирует все наборы данных в 1 файл, я понял, что внешние ссылки могут быть лучшим решением. Они устраняют дублированные копии данных. Единственный вопрос-это производительность. Код для ссылки почти идентичен. Я изменил свой ответ и код, чтобы показать оба метода.
kcw78

На других языках

Эта страница на других языках

Italiano
..................................................................................................................
Polski
..................................................................................................................
Română
..................................................................................................................
한국어
..................................................................................................................
हिन्दी
..................................................................................................................
Français
..................................................................................................................
Türk
..................................................................................................................
Česk
..................................................................................................................
Português
..................................................................................................................
ไทย
..................................................................................................................
中文
..................................................................................................................
Español
..................................................................................................................
Slovenský
..................................................................................................................