NVIDIA NeMo Framework-Schulungsjobs ausführen

NVIDIA NeMo Framework Launcher ist ein cloudnatives Tool zum Starten von End-to-End-Schulungsjobs im NeMo Framework für Tausende von GPUs für umfangreiche LLM-Schulungen. In diesem Beispiel verwenden wir den NeMo Framework Launcher, um das Sprachmodell gpt3_5b large, die Phasen der Datenvorbereitung und des Trainings auszuführen.

Weitere Informationen zu NeMo und dem NeMo Framework Launcher finden Sie in der NVIDIA-Dokumentation:

LLM-Schulungs-Workload ausführen

Installieren Sie python, und führen Sie eine Trainings-Workload aus.

  1. Installieren Sie python 3.8, und machen Sie es zum Standard-python für Benutzer opc.

    Für diese Python3 ist zusätzlich zu den in requirements.txt aufgeführten python-Modulen erforderlich. Oracle Linux 7 (und einige andere BS-Releases) lautet weiterhin python2.

    $ sudo yum install -y oracle-softwarecollection-release-el7
    $ sudo yum -y install scl-utils rh-python38
    $ scl enable rh-python38 bash
    $ cat <<EOF >> ~/.bashrc
    [ -f /opt/rh/rh-python38/enable ] && source /opt/rh/rh-python38/enable
    EOF
  2. Verwenden Sie die Installation-Befehle unter https://github.com/NVIDIA/NeMo-Megatron-Launcher.
    $ cd /nfs/scratch
    $ git clone https://github.com/NVIDIA/NeMo-Megatron-Launcher.git
    Cloning into 'NeMo-Megatron-Launcher'...
    remote: Enumerating objects: 29018, done.
    remote: Counting objects: 100% (1062/1062), done.
    remote: Compressing objects: 100% (452/452), done.
    remote: Total 29018 (delta 665), reused 898 (delta 564), pack-reused 27956
    Receiving objects: 100% (29018/29018), 27.66 MiB | 14.16 MiB/s, done.
    Resolving deltas: 100% (18124/18124), done.
    
    $ cd NeMo-Megatron-Launcher
    $ pip install -r requirements.txt --user
    $ pip install --upgrade requests --user

    Hinweis:

    Wenn andere Benutzer als opc das Cluster gemeinsam verwenden, müssen Sie die python-Module für alle Benutzer mit sudo pip install -r requirements.txt installieren.

Datenvorbereitung

Die Datenvorbereitungsphase führt drei Aufgaben aus: Laden Sie "den Stapel" uncopyrighted Dataset herunter, extrahieren (dekomprimieren) Sie die Daten und verarbeiten Sie die Daten vor.

  1. Bearbeiten Sie launcher_scripts/conf/config.yaml:
    1. Setzen Sie den Job stage auf data_preparation.
      stages:
        - data_preparation
        #- training
    2. Legen Sie launcher_scripts_path fest.
      # Path to NeMo Megatron Launch scripts, should ends with /launcher_scripts
      launcher_scripts_path: /nfs/scratch/NeMo-Megatron-Launcher/launcher_scripts
  2. Führen Sie im Verzeichnis launcher_scripts den Befehl main.py aus, um den Job an Slurm weiterzuleiten.
    $ cd /nfs/scratch/NeMo-Megatron-Launcher/launcher_scripts
    $ python main.py
    Job nemo-megatron-download_gpt3_pile submission file created at '/nfs/scratch/NeMo-Megatron-Launcher/launcher_scripts/results/download_gpt3_pile/download/nemo-megatron-download_gpt3_pile_submission.sh' 
    . . .
  3. Verwenden Sie den Slurm-Befehl squeue, um den Jobstatus zu überwachen.
    $ squeue
                 JOBID PARTITION     NAME     USER ST       TIME  NODES NODELIST(REASON)
        191_[20-29%30]       gpu nemo-meg      opc PD       0:00      1 (Resources)
            192_[0-29]       gpu nemo-meg      opc PD       0:00      1 (Dependency,Priority)
            193_[0-29]       gpu nemo-meg      opc PD       0:00      1 (Dependency)
                191_19       gpu nemo-meg      opc  R       0:50      1 gpu-permanent-node-517
                191_18       gpu nemo-meg      opc  R       0:56      1 gpu-permanent-node-878
    

    Jobs mit dem Status (ST) R geben an, dass einige Jobs ausgeführt werden. Andere angezeigte Jobs warten auf Ressourcen oder warten darauf, dass andere Jobs zuerst abgeschlossen werden (Abhängigkeiten).

    Suchen Sie in results/download_gpt3_pile/download, um die Ausgabe abgeschlossener und ausgeführter Jobs anzuzeigen. Sie finden auch das bash-Skript, mit dem die Slurm-Jobs übermittelt wurden. Das Skript und die Ausgabe können für die Fehlerbehebung bei Jobs nützlich sein, die nicht wie erwartet ausgeführt werden.
Bei einem Cluster mit zwei Knoten wurden folgende Schritte ausgeführt:
  • 90 Minuten zum Download
  • 46 Minuten zu extrahieren
  • 5 Std. 45 Minuten für die Vorverarbeitung
Die Laufzeiten wären bei einem größeren Cluster wesentlich niedriger, bei dem Data Shards auf bis zu 30 Knoten parallelisiert werden können.

Schulung

In der Schulungsphase bearbeiten Sie die Skripte, um LLM-Schulungen durchzuführen.

  1. Bearbeiten Sie launcher_scripts/conf/config.yaml:
    1. Setzen Sie den Job stage auf training.
      stages:
        #- data_preparation
        - training
    2. Fügen Sie Variablen hinzu, um NVIDIA NVLink auf OCI zu konfigurieren.
      Fügen Sie im Abschnitt env_vars diese Variablen hinzu, um NVIDIA NVLink auf OCI zu konfigurieren. Lassen Sie vorhandene Variablen an Ort und Stelle, kommentieren Sie jedoch alle Vars aus, die wir durch neue Werte ersetzen.
      env_vars:
        TRANSFORMERS_OFFLINE: 0 # (was 1)
        . . .
        RX_QUEUE_LEN: 8192
        IB_RX_QUEUE_LEN: 8192
        UCX_TLS: tcp
        HCOLL_ENABLE_MCAST_ALL: 0
        coll_hcoll_enable: 0
        UCX_NET_DEVICES: ens300
        NCCL_SOCKET_IFNAME: ens300
        NCCL_IB_TIMEOUT: 16
        NCCL_IB_SL: 0
        NCCL_IB_TC: 41
        NCCL_ALGO: Auto  # tree, ring
        NCCL_IB_GID_INDEX: 3
        NCCL_IB_QPS_PER_CONNECTION: 16  # was 4
        NCCL_IB_HCA: \'mlx5_1,mlx5_2,mlx5_3,mlx5_4,mlx5_5,mlx5_6,mlx5_7,mlx5_8,mlx5_9,mlx5_10,mlx5_11,mlx5_12,mlx5_14,mlx5_15,mlx5_16,mlx5_17\'
        NCCL_DEBUG: INFO # Logging level for NCCL. Set to "INFO" for debug information
  2. Bearbeiten Sie conf/training/gpt3/5b.yaml.
    run:
      time_limit: "6-00:00:00"  # allow the training job to run for 6 days
    
    trainer:
      num_nodes: 2 # (was 16) set to the size of your cluster
    
    model:
      micro_batch_size: 2           # (was 4) change to fit in A100/40GB memory
      tensor_model_parallel_size: 2 # (was 1) change to fit in A100/40GB memory
    
      optim:
        bucket_cap_mb: 200 # (was 400)
  3. Führen Sie im Verzeichnis launcher_scripts den Befehl main.py aus, um den Job an Slurm weiterzuleiten. Verwenden Sie den Befehl squeue, um zu prüfen, ob der Job ausgeführt wird ("R").
    $ cd /nfs/scratch/NeMo-Megatron-Launcher/launcher_scripts
    $ python main.py
    Job nemo-megatron-gpt3_5b submission file created at '/nfs/scratch/NeMo-Megatron-Launcher/launcher_scripts/results/gpt3_5b/nemo-megatron-gpt3_5b_submission.sh'
    Job nemo-megatron-gpt3_5b submitted with Job ID 285
    $ squeue
                 JOBID PARTITION     NAME     USER ST       TIME  NODES NODELIST(REASON)
                   285       gpu nemo-meg      opc  R       0:06      2 gpu-permanent-node-[517,878]
  4. Prüfen Sie die Dateien in results/gpt3_5b/*, um Ausgabe- und Fehlermeldungen anzuzeigen und den Fortschritt der ausgeführten Jobs zu überwachen.
    Das LLM-Training funktioniert, wenn in der gpt3_5b_nnn.out ähnliche Zeilen angezeigt werden:
    Training:   0%|          | 0/75375 [00:00<?]
    Epoch 0: :   0%|          | 0/75375 [00:00<?]
    Epoch 0: :   0%|          | 1/75375 [00:52<1089:12:32]
    Epoch 0: :   0%|          | 1/75375 [00:52<1089:13:02 ... train_step_timing in s=52.00]
    Epoch 0: :   0%|          | 2/75375 [01:33<980:51:18 ... train_step_timing in s=52.00]
    Epoch 0: :   0%|          | 2/75375 [01:33<980:51:33 ... train_step_timing in s=46.80]
    Epoch 0: :   0%|          | 3/75375 [02:15<945:29:05 ... train_step_timing in s=46.80]
    Epoch 0: :   0%|          | 3/75375 [02:15<945:29:14 ... train_step_timing in s=45.20]
    Epoch 0: :   0%|          | 4/75375 [02:57<926:40:09 ... train_step_timing in s=45.20]
    Epoch 0: :   0%|          | 4/75375 [02:57<926:40:16 ... train_step_timing in s=44.30]
    Epoch 0: :   0%|          | 5/75375 [03:38<915:10:14 ... train_step_timing in s=44.30]
    Epoch 0: :   0%|          | 5/75375 [03:38<915:10:20 ... train_step_timing in s=43.70]
    Epoch 0: :   0%|          | 6/75375 [04:20<907:25:47 ... train_step_timing in s=43.70]
    Epoch 0: :   0%|          | 6/75375 [04:20<907:25:52 ... train_step_timing in s=41.60]
    Epoch 0: :   0%|          | 7/75375 [05:01<901:53:34 ... train_step_timing in s=41.60]
    Epoch 0: :   0%|          | 7/75375 [05:01<901:53:38 ... train_step_timing in s=41.60]
    Epoch 0: :   0%|          | 8/75375 [05:43<897:38:17 ... train_step_timing in s=41.60]
    Epoch 0: :   0%|          | 8/75375 [05:43<897:38:21 ... train_step_timing in s=41.50]
    Epoch 0: :   0%|          | 9/75375 [06:24<894:16:56 ... train_step_timing in s=41.50]
    Epoch 0: :   0%|          | 9/75375 [06:24<894:16:59 ... train_step_timing in s=41.50]
    Epoch 0: :   0%|          | 10/75375 [07:05<891:30:50 ... train_step_timing in s=41.50]

    Dies bedeutet, dass jeder Trainingsschritt in 41,5 Sekunden abgeschlossen wurde. Mit mehr GPUs im Cluster können viel schnellere Schrittzeiten erreicht werden.