Problem wejścia / wyjścia podczas uruchamiania wielu dużych plików H5PY (Pytorch)

0

Pytanie

Zetknąłem się z problemem!

Ostatnio zetknąłem się z problemem wejścia / wyjścia. Docelowe i dane wejściowe są przechowywane w plikach h5py. Każdy plik docelowy wynosi 2,6 GB, a każdy plik wejściowy-10,2 GB. Mam 5 zestawów danych wejściowych i w sumie 5 docelowych zestawów danych.

Stworzyłem własną funkcję zestawu danych dla każdego pliku h5py, a następnie wykorzystał dane.Klasa ConcatDataset do komunikacji wszystkich zestawów danych. Funkcja własnego zestawu danych jest:

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])

Następnie używam dataset_train = data.ConcatDataset([MydataSet(indx=index, train=True) for index in range(1, 6)]) do treningów. Gdy używane są tylko 2-3 pliku h5py, prędkość wejścia / wyjścia normalna, i wszystko chodzi poprawnie. Jednak w przypadku 5 plików szybkość uczenia się stopniowo maleje (od 5 iteracji/s do 1 iteracji/z). Zmieniam num_worker, i problem nadal istnieje.

Czy ktoś może mi podpowiedzieć rozwiązanie? Czy mogę połączyć kilka plików h5py w jeden większy? Lub innymi metodami? Z góry dziękuję!

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

Najlepsza odpowiedź

1

Zwiększenie wydajności wymaga tymczasowych obiektów. Do tego trzeba określić potencjalne wąskie gardła i związane z nimi scenariuszy. Powiedział pan "z 2-3 plikami prędkość wejścia / wyjścia normalna" i "przy użyciu 5 plików szybkość uczenia się stopniowo maleje". Tak więc, twój problem z prędkością wejścia / wyjścia związane z wydajnością lub szybkością uczenia się? Czy ty wiesz? Jeśli nie wiesz, trzeba izolować i porównać wydajność wejścia / wyjścia i wydajność uczenia się oddzielnie dla 2 scenariuszy.
Innymi słowy, do pomiaru wydajności we / wy (tylko) należy wykonać następujące testy:

  1. Czas do odczytu i stowarzyszenia 2-3 plików,
  2. Czas do odczytu i stowarzyszenia 5 plików,
  3. Skopiuj 5 plików w 1 i zaobserwuj podczas wspólnego czytania z pliku,
  4. Lub połącz 5 plików z 1 plikiem i czasem.

I do pomiaru szybkości uczenia się (tylko) trzeba porównać wydajność dla następujących testów:

  • Połącz 2-3 pliku, a następnie przeczytaj i naucz się z połączonego pliku.
  • Połącz wszystkie 5 plików, a następnie przeczytaj i naucz się z połączonego pliku.
  • Lub połącz 5 plików z 1 plikiem, a następnie przeczytaj i dowiedz się z połączonego pliku.

Jak wspomniano w moim komentarzu, połączyć (lub link) kilka plików HDF5 w jeden łatwe, jeśli wszystkie zbiory danych znajdują się na poziomie głównym, a wszystkie nazwy zestawów danych są wyjątkowe. Dodałem metodę linków zewnętrznych, bo to może zapewnić taką samą wydajność bez powielania dużych plików danych.

Poniżej znajduje się kod, który pokazuje obie metody. Podstawiając swoje nazwy plików w fnames lista, i powinien być gotowy do uruchomienia. Jeśli nazwy swoich zestawów danych nie są wyjątkowe, trzeba będzie stworzyć unikalne nazwy i wyznaczyć w h5fr.copy() -- tak: h5fr.copy(h5fr[ds],h5fw,'unique_dataset_name')

Kod do konsolidacji lub łączenia plików :
(komentarz/odkomentuj linie w razie potrzeby)

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

Po opublikowaniu kodu, który kopiuje wszystkie zestawy danych w 1 plik, zdałem sobie sprawę, że linki zewnętrzne mogą być najlepszym rozwiązaniem. Eliminują one powielone kopie danych. Jedyna kwestia to wydajność. Kod do linki jest prawie identyczny. Zmieniłem swoją odpowiedź i kod, aby pokazać obie metody.
kcw78

W innych językach

Ta strona jest w innych językach

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