Ejecutar trabajos de formación de marco NVIDIA NeMo

NVIDIA NeMo Framework Launcher es una herramienta nativa de la nube para iniciar trabajos de formación de NeMo Framework de extremo a extremo en miles de GPU para la formación de LLM a gran escala. En este ejemplo, utilizamos NeMo Framework Launcher para ejecutar el modelo de lenguaje gpt3_5b large, las etapas de preparación de datos y entrenamiento.

Consulte la documentación de NVIDIA para obtener más información sobre NeMo y NeMo Framework Launcher:

Ejecución de una carga de trabajo de formación de LLM

Instale python y ejecute una carga de trabajo de formación.

  1. Instale python 3.8 y conviértalo en el python por defecto para el usuario opc.

    Para este Python3 es necesario, además de los módulos de python que se muestran en requirements.txt. Oracle Linux 7 (y otras versiones del sistema operativo) aún son 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. Utilice los comandos Installation en 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

    Note:

    Si los usuarios que no sean opc compartirán el cluster, deberá instalar los módulos de python para todos los usuarios con: sudo pip install -r requirements.txt.

Preparación de Datos

La etapa de preparación de datos realiza tres tareas: descargar el juego de datos sin derechos de autor de "la pila", extraer (descomprimir) los datos y procesar previamente los datos.

  1. Edite launcher_scripts/conf/config.yaml:
    1. Defina el trabajo stage en data_preparation.
      stages:
        - data_preparation
        #- training
    2. Defina launcher_scripts_path.
      # Path to NeMo Megatron Launch scripts, should ends with /launcher_scripts
      launcher_scripts_path: /nfs/scratch/NeMo-Megatron-Launcher/launcher_scripts
  2. En el directorio launcher_scripts, ejecute main.py para ejecutar el trabajo en Slurm.
    $ 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. Utilice el comando squeue de Slurm para observar el estado del trabajo.
    $ 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
    

    Los trabajos con estado (ST) R indican que algunos de los trabajos se están ejecutando. Otros trabajos que se muestran están esperando recursos o esperando a que otros trabajos se completen primero (dependencias).

    Consulte results/download_gpt3_pile/download para ver la salida de los trabajos terminados y en ejecución. También puede encontrar el script bash que se utilizó para ejecutar los trabajos de Slurm. La secuencia de comandos y la salida pueden ser útiles para solucionar problemas de trabajos que no se ejecutan como se esperaba.
En un cluster de dos nodos, se han realizado los siguientes pasos:
  • 90 minutos para descargar
  • 46 minutos para extraer
  • 5 horas 45 minutos para preprocesamiento
Los tiempos de ejecución serían sustancialmente más bajos en un cluster más grande donde las particiones horizontales de datos se pueden paralelizar en hasta 30 nodos.

Formación

En la etapa de formación, editará los scripts para realizar la formación de LLM.

  1. Edite launcher_scripts/conf/config.yaml:
    1. Defina el trabajo stage en training.
      stages:
        #- data_preparation
        - training
    2. Agregue variables para configurar NVIDIA NVLink en OCI.
      En la sección env_vars, agregue estas variables para configurar NVIDIA NVLink en OCI. Deje las variables existentes en su lugar, pero comente las vars que estamos reemplazando con nuevos valores.
      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. Edite 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. En el directorio launcher_scripts, ejecute main.py para ejecutar el trabajo en Slurm. Utilice el comando squeue para verificar que el trabajo se está ejecutando ("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. Consulte los archivos de results/gpt3_5b/* para ver los mensajes de salida y de error y supervisar el progreso de los trabajos en ejecución.
    La formación de LLM funciona si ve líneas similares a esta en gpt3_5b_nnn.out:
    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]

    Esto indica que cada paso de entrenamiento se completa en 41,5 segundos. Se pueden lograr tiempos de paso mucho más rápidos con más GPU en el cluster.