Artikeln skrevs av Rakshith Vasudev och John Lockman på HPC AI Innovation Lab i oktober 2019
Som tidigareintroducerades är CheXNet en AI-modell för radiologiassistenter som använder DenseNet för att identifiera upp till 14 pathologier från en viss ray-bild. Flera metoder utforskades för att skala ut utbildningen av en modell som skulle kunna fungera lika väl som eller bättre än den ursprungliga CheXNet-121 med ResNet-50 som uppvisar löftet både vad gäller skalbarhet och ökad noggrannhet i utbildningen (positiv AUROC). Skaparna visade skalbarhet på CPU-system, men vi är intresserade av att utnyttja parallellismen hos grafikprocessorer för att snabba upp inlärningsprocessen. I den här artikeln beskriver vi bästa praxis för att uppnå maximala prestanda på distribuerad utskalningsutbildning för CheXNet med nvidia V100 SXM2-grafikprocessorer i Dell EMC C4140-servrar. Dell EMC PowerEdge C4140 ger både densitet och prestanda med fyra Nvidia V100-grafikprocessorer i SXM2-konfiguration.
Maskinvarukonfiguration: | Programvarukonfiguration: |
---|---|
|
|
Eftersom nya datorenheter (t.ex. grafikprocessorer och TPU:er) gör det möjligt att träna neurala nätverk med en allt snabbare hastighet tenderar processorbearbetningen att bli flaskhals. tf.data API ger användarna byggstenar för att utforma inmatningsflöden som effektivt använder processorn och optimerar varje steg i ETL-processen.
För att utföra ett utbildningssteg måste du först extrahera och omvandla utbildningsdata och sedan skicka dem till en modell som körs på en accelerator. Men i en nandetve-synkron implementering är acceleratorn i viloläge medan processorn förbereder data. Omvänt gäller att processorn är i viloläge medan acceleratorn finjusterar modellen. Utbildningsstegstiden är alltså summan av både processorförbearbetningstiden och acceleratorutbildningstiden
Pipelining överlappar förprocessing och modellkörning av ett utbildningssteg. Medan acceleratorn utför utbildningssteg N förbereder processorn data för steg N+1. På så sätt minskar du stegtiden till den maximala (till skillnad från summan) av utbildningen och den tid det tar att extrahera och omvandla data.
Utan pipelining är processorn och GPU:n/TPU:n inaktiva en stor del av tiden:
Bild 1: Sekventiell körning gör ofta att GPU:n blir inaktiv
Med pipelining minskar den inaktiva tiden avsevärt:
Bild 2: Pipelining överlappar processor- och GPU-användning och maximerar GPU-användning
tf.data API tillhandahåller en mekanism för programvaruanalys via tf.data.Dataset.prefetch-övergång, som kan användas för att frikoppla tidsdata från den tidpunkt då de förbrukas. I övergången används en bakgrundstråd och en intern buffert för förhämtning av element från indatauppsättningen innan de begärs.
Mer information finns här: https://www.tensorflow.org/guide/performance/datasets
När man följer riktlinjerna från Tensorflow är det möjligt att få en datapipeline som ser ut så här (gammal metod):
https://github.com/dellemc-hpc-ai/code-examples/blob/master/cheXNet-snippets/old_approach.py
I det här tillvägagångssättet, som även kallas det gamla tillvägagångssättet, gör tf data pipeline följande (förutsatt att den uttända x ray-datauppsättningen är en sekvens av TFRecords):
Det här är dock inte den kod som fungerar mest. Det orsakar fördröjningar och 0 % gpu-användning ofta. I grunden använder den inte acceleratorerna på ett effektivt sätt.
För att korrekt konfigurera tf data pipeline följer vi den metod som tensorflows officiella modeller har vidtagit, särskilt den för ResNet. Skillnaden mellan den gamla metoden och den nya metoden är hur data pipelinen konfigureras innan den matas in på modellen.
Så här ser det nya tillvägagångssättet ut:
https://github.com/dellemc-hpc-ai/code-examples/blob/master/cheXNet-snippets/new_approach.py
TensorFlows officiella modellutformning kallas även för en ny metod:
Här är en jämförelse av prestandan hos både gamla och nya metoder, med hjälp av TF:s officiella modeller.
Bild 3: Med den nya metoden kan det vara nära linjär skalning.
Som det kan ses finns det ett betydande prestandaproblem och det finns ingen skalning alls med det gamla tillvägagångssättet. GPU:er skulle ofta uppleva liten eller ingen användning, vilket gör att prestandan planas ut. Att effektivisera beräkning på en grafikprocessor innebär att beräkning blir mer effektiv på flera grafikprocessorer på flera noder om kommunikationen hanteras korrekt.
Att ha processorer utför förbearbetning parallellt, och förhämtning av bearbetade data i minnet och grafikprocessorer som utför det tunga lyftet av matris multiplikering med snabb kommunikation är en annan aspekt som gör detta nya synsätt mer intressant att skala för multinoder.
Miljön som kör dina jobb är lika viktig som dina jobb, eftersom det är viktigt att ha rätt bibliotek/moduler, eftersom de påverkar utbildningsprestandan. Att även ha de senaste CUDA-relaterade biblioteken kan bidra till bättre prestanda.
Följ den här självstudiekursen för att installera om du inte har en arbetsmiljö.
MPI är ett kommunikationsbibliotek som skapar horovod för att distribuera jobb. Olika bindnings- och mappningsparameteralternativ utforskades och de bästa parametrarna för C4140 mappades efter sockel. Den rekommenderade inställningen är som följer:mpirun --map-by socket -np x python pyfile.py --pyoptions
Om det finns mer än en process som fungerar med en grafikprocessor kan de mycket väl vara till nytta för GPU-resurser, konsumera GPU-minne och i själva verket inte montera fler bilder per batch, vilket innebär att det är ansvarigt för att GPU-prestandan ska påverkas. Tensorflow 1.13.1 utforskades, men det verkar som om det hade en bugg vid den tidpunkten. Fler än en process per grafikprocessor startades.
Sammanfattning: