Skip to main content
  • Place orders quickly and easily
  • View orders and track your shipping status
  • Enjoy members-only rewards and discounts
  • Create and access a list of your products

Tecniche di ottimizzazione per la formazione di CheXNet su Dell C4140 con GPU NVIDIA V100 (in inglese)

Summary: Best practice per ottenere massime prestazioni sulla formazione scale-out distribuita di CheXNet che utilizza GPU NVIDIA V100 SXM2 nei server Dell EMC C4140.

This article applies to This article does not apply to This article is not tied to any specific product. Not all product versions are identified in this article.

Symptoms

Questo articolo è stato scritto da Rakshith Vasudev e John Lockman - HPC AI Innovation Lab, nell'ottobre 2019

Cause

  -

Resolution

Come introdotto in precedenza,CheXNet è un modello di assistente radilogo di intelligenza artificiale che utilizza DenseNet per identificare fino a 14 patologie da una determinata immagine di radiografia del toraco. Sono stati analizzati diversi approcci per scalare l'addestramento di un modello che potesse funzionare in modo ottimale o superiore rispetto al CheXNet-121 originale con ResNet-50 dimostrando la promessa sia in termini di scalabilità che di maggiore precisione dell'addestramento (AUROC positivo). Gli autori hanno dimostrato scalabilità sui sistemi cpu, tuttavia siamo interessati a sfruttare il parallelismo delle GPU per accelerare il processo di formazione. In questo articolo vengono descritte le best practice per ottenere massime prestazioni sulla formazione scale-out distribuita di CheXNet utilizzando le GPU NVIDIA V100 SXM2 nei server Dell EMC C4140. Dell EMC PowerEdge C4140 fornisce densità e prestazioni con quattro GPU NVIDIA V100 in configurazione SXM2.


 

Configurazione hardware: Configurazione software:
  • 4 PowerEdge C4140
  • 4 NVIDIA V100 32 GB SXM2
  • 2 CPU Intel(R) Xeon(R) Gold 6148 a 20 core da 2,4 GHz
  • 384 GB di RAM, DDR4, 2.666 MHz
  • 1 Mellanox EDR HCA
  • File system Lustre
  • Framework di apprendimento approfondito: tensorflow-gpu
  • Versione framework: 1.12.0
  • Versione Horovod: 0.16.4
  • Versione MPI: 4.0.0 con supporto cuda e ucx
  • Versione CUDA: 10.1.105
  • Versione CUDNN: 7.6.0
  • Versione NCCL: 2.4.7
  • Versione Python: 3.6.8
  • Sistema operativo e versione: RHEL 7.4


 


La pipeline dei dati è fondamentale per ottenere il massimo delle prestazioni dagli acceleratori:



 

Che cos'è tf data, perché si dovrebbe tentare di utilizzarli?

 

Poiché i nuovi dispositivi di elaborazione (come GPU e TPU) consentono di addestrare le reti neurali a un ritmo sempre più veloce, l'elaborazione della CPU è incline a diventare il collo di bottiglia. L'API tf.data fornisce agli utenti elementi di base per progettare pipeline di input che utilizzano in modo efficace la CPU, ottimizzando ogni fase del processo ETL.

 

Per eseguire una fase di formazione, è innanzitutto necessario estrarre e trasformare i dati di formazione, quindi inviarli a un modello in esecuzione su un acceleratore. Tuttavia, in un'implementazione sincrona NAVE, mentre la CPU sta preparando i dati, l'acceleratore è inattivo. Al contrario, mentre l'accelerator sta addestrando il modello, la CPU è inattiva. La fase di formazione è quindi la somma del tempo di pre-elaborazione della CPU e del tempo di formazione dell'acceleratore

 

La pipelining si sovrappone alla pre-elaborazione e all'esecuzione del modello di una fase di addestramento. Mentre l'acceleratore esegue il passaggio di formazione N, la CPU sta preparando i dati per il passaggio N+1. In questo modo si riduce il tempo di passaggio al massimo (anziché la somma) della formazione e il tempo necessario per estrarre e trasformare i dati.

 

Senza pipelining, la CPU e la GPU/TPU restano inattive per la maggior parte del tempo:

SLN318898_en_US__1Sequantial'esecuzione
Fig. 1: L'esecuzione sequenziale lascia spesso la GPU inattiva

 

Con la pipelining, il tempo di inattività diminuisce in modo significativo:

SLN318898_en_US__2Pipelining si sovrappongono
Fig. 2: La pipelining si sovrappone all'utilizzo di CPU e GPU, ottimizzando l'utilizzo della GPU

 

L'API tf.data fornisce un meccanismo di pipelining del software tramite la trasformazione tf.data.Dataset.prefetch, che può essere utilizzata per disaccoppiare il tempo di produzione dei dati dal momento in cui vengono utilizzati. In particolare, la trasformazione utilizza un thread in background e un buffer interno per eseguire il pre-fetch degli elementi dal dataset di input prima del momento in cui vengono richiesti.

 

Ulteriori informazioni qui: https://www.tensorflow.org/guide/performance/datasets

 

Quando si seguono le linee guida fornite da tensorflow, è possibile ottenere una pipeline di dati simile a questa (approccio precedente):
https://github.com/dellemc-hpc-ai/code-examples/blob/master/cheXNet-snippets/old_approach.py

 

In questo approccio definito anche come il vecchio approccio, la pipeline di dati tf fa quanto segue (supponendo che il dataset del tondo x ray sia una sequenza di TFRecords):

 

  1. Ottiene l'elenco assoluto dei nomi di file.
  2. Crea un dataset dall'elenco dei nomi di file utilizzando TFRecordDataset()
  3. Creare un nuovo dataset che carichi e formatta le immagini mediante la pre-elaborazione.
  4. Shard del dataset.
  5. Sfumare il dataset durante l'addestramento.
  6. Ripetere il dataset.
  7. Batch del dataset.
  8. Pre-fetch del dataset per il batch_size.


 

Tuttavia, questo non è il codice più performante. Provoca stalli e frequenti utilizzo di GPU dello 0%. Fondamentalmente, non utilizza gli acceleratori in modo efficace.

Per configurare correttamente la pipeline di dati tf, seguiamo l'approccio adottato specificamente dai modelli ufficiali tensorflow,quello per ResNet.  La differenza tra il vecchio approccio e il nuovo approccio è il modo in cui viene configurata la pipeline di dati prima di passare al modello.

 

Ecco come si presenta il nuovo approccio:
https://github.com/dellemc-hpc-ai/code-examples/blob/master/cheXNet-snippets/new_approach.py

 

L'approccio ufficiale dei modelli TensorFlow, definito anche nuovo approccio, è il seguente:

 

  1. Ottiene l'elenco assoluto dei nomi di file.
  2. Crea un dataset dall'elenco dei nomi di file utilizzando from_tensor_slices()
  3. Lo sharding viene eseguito in anticipo.
  4. Il dataset viene sfrenato durante l'addestramento.
  5. Il dataset viene quindi interlacciato in parallelo, ovvero l'interfoliazione e l'elaborazione di più file (definiti da cycle_length) per trasformarli per creare dataset TFRecord.
  6. Viene quindi eseguito il pre-fetched del dataset. Il buffer_size definisce il numero di record con pre-fetched, che in genere è il mini batch_size del job.
  7. Il dataset viene nuovamente scontrollato. I dettagli della riproduzione casuale sono controllati da buffer_size.
  8. Il dataset viene ripetuto.  Ripete il dataset fino a quando non num_epochs il training.
  9. Il dataset è soggetto a map_and_batch() simultanei che analizza i file di record tf, che a sua volta pre-elabora l'immagine e li esegue in batch.
  10. L'immagine pre-elaborazione è pronta come dataset e viene eseguito nuovamente il pre-fetched.


 

Ecco un confronto delle prestazioni di entrambi gli approcci vecchi e nuovi, utilizzando i modelli ufficiali TF.

SLN318898_en_US__3image (12053)
Fig. 3: Con il nuovo approccio, ci si potrebbe aspettare un dimensionamento quasi lineare.

 

Come si può vedere, c'è un significativo calo delle prestazioni e non vi è alcun dimensionamento con il vecchio approccio. Le GPU riscontrano spesso un utilizzo ridotto o nullo, con conseguente riduzione delle prestazioni. Rendere il calcolo più efficiente su una GPU significa rendere il calcolo più efficiente su più GPU su più nodi, se la comunicazione viene gestita correttamente.
Poiché le CPU eseguono la pre-elaborazione in parallelo, il pre-fetch dei dati elaborati in-memory e le GPU che eseguono il pesante sollevamento della moltiplicazione di matrice con una comunicazione rapida sono un altro aspetto che rende questo nuovo approccio più interessante da scalare per i nodi multipli.


 


Altre tecniche da esaminare per ottenere prestazioni ottimali:



 

Avere l'ambiente corretto è importante:

 

L'ambiente che esegue i job è importante quanto quello dei job, perché avere le librerie/i moduli giusti è importante in quanto influirà sulle prestazioni di formazione. Inoltre, disporre delle librerie CUDA più recenti può contribuire a migliorare le prestazioni.

Seguire questa esercitazione per eseguire l'installazione, se non si dispone di un ambiente di lavoro configurato.



 

Utilizzando i parametri di binding corretti per MPI:

 

MPI è una libreria di comunicazioni che aiuta horovod a distribuire i lavori. Sono state analizzate diverse opzioni di parametro di binding e mapping e i parametri migliori per C4140 sono stati mappati per socket. L'impostazione consigliata è la seguente:
mpirun --map-by socket -np x python pyfile.py --pyoptions



 

Assicurarsi che un processo agisca su una GPU:

 

Se sono presenti più processi che funzionano una gPU, potrebbero essere molto efficaci nel combattere per le risorse GPU, consumando memoria GPU e non inserendo in modo efficace più immagini per batch, quindi responsabili di rendere le prestazioni della GPU un hit. Tensorflow 1.13.1 è stato esplorato, ma sembra che all'epoca avesse un bug. È stato avviato più di un processo per GPU.


 

In breve:

  • La corretta configurazione della pipeline di dati è fondamentale per visualizzare l'aumento delle prestazioni.
  • La configurazione dell'ambiente corretto contribuisce a migliorare le prestazioni.
  • L'utilizzo dei parametri di binding corretti per MPI contribuisce a migliorare le prestazioni.
  • Profilo e correzione dei colli di bottiglia quando le GPU non sono completamente utilizzate.


 


Affected Products

High Performance Computing Solution Resources, Poweredge C4140
Article Properties
Article Number: 000124384
Article Type: Solution
Last Modified: 17 Sep 2021
Version:  5
Find answers to your questions from other Dell users
Support Services
Check if your device is covered by Support Services.