Artykuł został napisany przez Rakshitha Vasudeva i Johna Lockmana z HPC AI Innovation Lab w październiku 2019 r.
Jak wspomniano wcześniej, CheXNet jest modelem opartego na sztucznej inteligencji asystenta radiologicznego, który z użyciem DenseNet identyfikuje do 14 zmian patologicznych w danym obrazie rentgenowskim klatki piersiowej. Zbadano kilka podejść w celu skalowania szkoleń modelu, który może działać równie dobrze lub lepiej niż oryginalny CheXNet-121 z ResNet-50, spełniając obietnice zarówno skalowalności, jak i większej dokładności szkoleń (pozytywne AUROC). Autorzy wykazali skalowalność w systemach procesorów, jednak chcemy wykorzystać równoległość procesorów graficznych w celu przyspieszenia procesu szkoleniowego. W tym artykule opisano najlepsze praktyki w celu osiągnięcia maksymalnej wydajności na szkoleniach w zakresie rozproszonego skalowania w CheXNet z wykorzystaniem kart graficznych Nvidia V100 SXM2 w serwerach Dell EMC C4140. Serwer Dell EMC PowerEdge C4140 zapewnia gęstość i wydajność dzięki czterem kartom graficznym Nvidia V100 w konfiguracji SXM2.
Konfiguracja sprzętu: | Konfiguracja oprogramowania: |
---|---|
|
|
Ponieważ nowe urządzenia obliczeniowe (takie jak procesory graficzne i jednostki TPU) umożliwiają szkolenie sieci neuronowych z coraz większą szybkością, przetwarzanie procesora może stać się wąskim gardłem. Interfejs API tf.data zapewnia użytkownikom elementy konstrukcyjne do projektowania wejściowych kanałów przepływu danych, które efektywnie wykorzystują procesor, optymalizując każdy etap procesu ETL.
Aby wykonać etap szkolenia, należy najpierw wyodrębnić i przekształcić dane szkoleniowe, a następnie przesłać je do modelu działającego na akceleratorze. Jednak w przypadku naiwnej synchronicznej implementacji podczas przygotowywania danych przez procesor, akcelerator jest bezczynny. Z kolei gdy akcelerator szkoli model, procesor jest bezczynny. Czas etapu szkolenia jest więc sumą czasu wstępnego przetwarzania procesora i czasu szkolenia akceleratora
Przetwarzanie potokowe nakłada się na przetwarzanie wstępne i wykonanie modelu etapu szkoleniowego. Podczas gdy akcelerator wykonuje etap szkolenia N, procesor przygotowuje dane do etapu N+1. Pozwala to skrócić czas etapu do maksimum (w przeciwieństwie do sumy) szkolenia i czasu potrzebnego na wyodrębnienie i transformację danych.
Bez przetwarzania potokowego, procesor i procesor graficzny/TPU przez większość czasu są bezczynne:
Rys. 1: Wykonywanie sekwencyjne często pozostawia procesor GPU w stanie bezczynności
W przypadku przetwarzania potokowego czas bezczynności znacznie się zmniejsza:
Rys. 2: Przetwarzanie potokowe nakłada się na wykorzystanie procesora i procesora graficznego, maksymalizując wykorzystanie procesora graficznego
Interfejs API tf.data zapewnia mechanizm przetwarzania potokowego oprogramowania poprzez transformację tf.data.Dataset.prefetch, którą można wykorzystać do odłączania czasu, w którym produkowane są dane od czasu, w którym są używane. Transformacja wykorzystuje wątek tła i bufor wewnętrzny do wstępnego pobierania elementów z zestawu danych wejściowych przed terminem ich zażądania.
Więcej informacji: https://www.tensorflow.org/guide/performance/datasets
Postępując zgodnie z wytycznymi zapewnianymi przez tensorflow można uzyskać kanał przepływu danych, który wygląda tak (stare podejście):
https://github.com/dellemc-hpc-ai/code-examples/blob/master/cheXNet-snippets/old_approach.py
W tym podejściu, zwanym również starym podejściem, kanał przepływu danych tf wykonuje następujące czynności (zakładając, że zestaw danych obrazu rentgenowskiego klatki piersiowej jest sekwencją TFRecords):
Nie jest to jednak najbardziej wydajny kod. Powoduje wstrzymanie i częste wykorzystanie procesora graficznego na 0%. Zasadniczo nie wykorzystuje efektywnie akceleratorów.
Aby poprawnie skonfigurować kanał przepływu danych tf, postępujemy zgodnie z podejściem podjętym przez oficjalne modele tensorflow, w szczególności dla ResNet. Różnica między starym podejściem a nowym podejściem polega na sposobie konfiguracji kanału przepływu danych przed wprowadzeniem go do modelu.
Oto jak wygląda nowe podejście:
https://github.com/dellemc-hpc-ai/code-examples/blob/master/cheXNet-snippets/new_approach.py
Podejście oficjalnych modeli TensorFlow, określane również mianem nowego podejścia, jest następujące:
Poniżej przedstawiono porównanie wydajności starych i nowych podejść przy użyciu oficjalnych modeli TF.
Rys. 3: Dzięki nowemu podejściu można było spodziewać się skalowania bliskiego liniowemu.
Jak widać, występuje znaczny spadek wydajności i nie ma żadnego skalowania w przypadku starego podejścia. Procesory graficzne często doświadczają niewielkiego wykorzystania lub jego braku, co powoduje obniżenie wydajności. Zwiększenie wydajności obliczeń na jednym procesorze GPU przekłada się na zwiększenie wydajności obliczeń w wielu GPU w wielu węzłach, jeśli komunikacja jest sprawna.
Wywołanie równolegle wstępnego przetwarzania przez procesory GPU, wstępne pobieranie przetworzonych danych w pamięci i ciężka praca procesorów GPU przy mnożeniu macierzy poprzez szybką komunikację to kolejny aspekt, który podnosi atrakcyjność nowego podejścia przy skalowaniu dla wielu węzłów.
Środowisko pracy jest równie ważne jak zadania, ponieważ ważne są odpowiednie biblioteki/moduły, jako że mają wpływ na wydajność szkoleń. Ponadto posiadanie najnowszych bibliotek związanych z CUDA może przyczynić się do poprawy wydajności.
Jeśli nie masz konfiguracji środowiska roboczego, postępuj zgodnie z tym samouczkiem instalacji.
MPI to biblioteka komunikacyjna, która ułatwia dystrybucję zadań horovod. Zbadano różne opcje parametrów powiązania i mapowania, a najlepszymi parametrami dla C4140 było mapowanie przez gniazdo. Zalecane ustawienie jest następujące:mpirun --map-by socket -np x python pyfile.py --pyoptions
Jeśli istnieje więcej niż jeden proces, który działa na jednym GPU, procesy te mogą równie dobrze walczyć o zasoby GPU, zużywając pamięć GPU i faktycznie nie dopasowując większej liczby obrazów na partię, w związku z czym są odpowiedzialne za utratę wydajności GPU. Eksplorowano tensorflow 1.13.1, ale wygląda na to, że występował błąd. Uruchamiał się więcej niż jeden proces na GPU.
Podsumowując: