Passer à la navigation

Profilage GPU avec Nsys

Afficher en Markdown

NeMo RL prend en charge le profilage Nsight pour les workers Ray via une correspondance de motifs de variables d’environnement. Cela vous permet de profiler de manière sélective des types de workers spécifiques sans modifier le code ou affecter les performances des workers qui n’ont pas besoin de profilage.

Remarque : Pour éviter que les fichiers de profil ne deviennent trop volumineux, pensez à limiter le profilage à un nombre restreint d’étapes (par exemple, 10 étapes).

Prérequis

Remarque : Si vous utilisez des conteneurs NeMo RL, nsys est déjà installé.

  • Assurez-vous que les workers que vous voulez profiler ont accès au GPU

Configurer les Variables d’Environnement

Définissez la variable d’environnement NRL_NSYS_WORKER_PATTERNS avec une liste de motifs séparés par des virgules pour correspondre aux noms des workers :

export NRL_NSYS_WORKER_PATTERNS="*policy*,*vllm*"

Définissez la variable d’environnement NRL_NSYS_PROFILE_STEP_RANGE pour contrôler les étapes d’entraînement capturées par le profileur. Son format est des entiers séparés par des deux-points représentant start:stop, où start est inclusif et stop est exclusif (comme la syntaxe de tranche arr[start:stop]). Notez que le start est à l’index 1, donc NRL_NSYS_PROFILE_STEP_RANGE=0:10 générerait une erreur.

export NRL_NSYS_PROFILE_STEP_RANGE=3:5

Format du Motif

  • Utilisez des caractères génériques de style shell (*, ?, [seq], [!seq])
  • Les motifs sont comparés aux noms des workers en utilisant fnmatch
  • Plusieurs motifs sont séparés par des virgules
  • Les espaces autour des motifs sont automatiquement supprimés
  • Les motifs vides sont ignorés

Workers Pris en Charge

Les types de workers pris en charge sont :

  • DTensorPolicyWorker : Motif comparé à "dtensor_policy_worker"
  • VllmGenerationWorker : Motif comparé à "vllm_generation_worker"

Exemple d’Utilisation

Profiler Uniquement les Workers de Politique

NRL_NSYS_PROFILE_STEP_RANGE=2:3 NRL_NSYS_WORKER_PATTERNS="*policy*" uv run examples/run_grpo_math.py grpo.max_num_steps=5

Profiler Plusieurs Types de Workers

NRL_NSYS_PROFILE_STEP_RANGE=1:2 NRL_NSYS_WORKER_PATTERNS="*policy*,*vllm*" uv run examples/run_grpo_math.py grpo.max_num_steps=5

Profiler des Workers avec des Noms Exacts

NRL_NSYS_PROFILE_STEP_RANGE=3:10 NRL_NSYS_WORKER_PATTERNS="dtensor_policy_worker,vllm_generation_worker" uv run examples/run_grpo_math.py grpo.max_num_steps=5

Profiler des Workers Megatron

Pour profiler un worker Megatron, vous devez définir LD_LIBRARY_PATH comme suit, sinon vous rencontrerez des erreurs lors du chargement de libtransformer_engine.so.

LD_LIBRARY_PATH="/usr/local/cuda/targets/x86_64-linux/lib:/usr/local/cuda/lib64:/usr/local/cuda/lib:/usr/local/nvidia/lib64:/usr/local/nvidia/lib:/usr/lib/x86_64-linux-gnu" \
NRL_NSYS_PROFILE_STEP_RANGE=2:3 NRL_NSYS_WORKER_PATTERNS="megatron_policy_worker,vllm_generation_worker" uv run examples/run_grpo_math.py --config examples/configs/grpo_math_1B_megatron.yaml grpo.max_num_steps=5

Sortie du Profil

Lorsque le profilage est activé, il génère les journaux et fichiers suivants :

  1. Journalisation : Vous verrez des messages de journalisation indiquant quels workers ont le profilage activé :

    Nsight profiling enabled for worker 'dtensor_policy_worker' (matched pattern '*policy*')
  2. Fichiers de Profil : Chaque worker profilé génère un fichier .nsys-rep avec le motif de nom suivant :

    dtensor_policy_worker_<NRL_NSYS_PROFILE_STEP_RANGE>_<PID>.nsys-rep
    vllm_generation_worker_<NRL_NSYS_PROFILE_STEP_RANGE>_<PID>.nsys-rep
    worker_process_<PID>.nsys-rep

Si vous n’utilisez pas le parallélisme de modèle dans Vllm, vous devez directement vous référer à vllm_generation_worker_<NRL_NSYS_PROFILE_STEP_RANGE>_<PID>.nsys-rep pour les rapports Nsight ; Si vous utilisez le parallélisme de modèle, le vllm_generation_worker_<NRL_NSYS_PROFILE_STEP_RANGE>_<PID>.nsys-rep sera vide, et les worker_process_<PID>.nsys-rep seront des profils Nsight provenant des exécuteurs distribués Ray de vllm (reportez-vous à https://github.com/vllm-project/vllm/blob/7e3a8dc90670fd312ce1e0d4eba9bf11c571e3ad/vllm/executor/ray_distributed_executor.py#L136 pour plus d’informations).

  1. Emplacement des Fichiers : Les fichiers de profil sont enregistrés dans le répertoire /tmp/ray/session*/logs/nsight/ sur chaque nœud worker. Assurez-vous de vérifier à la fois ls /tmp/ray/session_[0-9]*/logs/nsight et ls /tmp/ray/session_latest/logs/nsight pour les profils, car le pointeur “latest” peut être obsolète.

Remarque pour les utilisateurs de SLURM avec ray.sub : Lors de l’utilisation de ray.sub sur SLURM, définissez RAY_LOG_SYNC_FREQUENCY=$NUM_SEC (par exemple, RAY_LOG_SYNC_FREQUENCY=30) pour vous assurer que les fichiers de profil Nsight sont copiés du système de fichiers éphémère du conteneur (/tmp/ray) vers le répertoire persistant. Les fichiers du nœud d’en-tête seront synchronisés vers “SLURMJOBID−logs/ray‘,etlesfichiersdesautresnœudsserontsynchroniseˊsvers‘SLURM_JOB_ID-logs/ray`, et les fichiers des autres nœuds seront synchronisés vers `SLURM_JOB_ID-logs/ray/nodeip/‘ouˋ‘node_ip/` où `node_ip` est l’adresse IP du nœud.

Analyser les Fichiers de Profil

Pour analyser les fichiers de profil générés, chargez les fichiers .nsys-rep dans l’application de bureau NVIDIA Nsight Systems, que vous pouvez télécharger sur la page de démarrage de NVIDIA Nsight Systems.

Comment Nous Avons Corrigé la Prise en Charge de Nsight dans Ray

La prise en charge du profilage Nsight dans Ray présentait un bogue où le chemin de l’exécutable Python était codé en dur au lieu d’utiliser l’exécutable Python réel de l’environnement d’exécution. Cela causait des problèmes lors de l’utilisation d’environnements virtuels ou d’installations Python personnalisées (py_executables).

Le Problème

Dans le fichier nsight.py de Ray, le code original était :

context.py_executable = " ".join(self.nsight_cmd) + " python"

Cela codait en dur " python" au lieu de préserver correctement le chemin de l’exécutable Python prévu.

La Correction

Pour résoudre ce problème, nous avons corrigé la ligne suivante pour préserver le context.py_executable original :

context.py_executable = " ".join(self.nsight_cmd) + f" {context.py_executable}"

Où Nous Avons Appliqué la Correction

Nous avons appliqué cette correction à deux endroits pour couvrir différents scénarios de déploiement :

  1. Dans ray.sub (clusters SLURM) : La correction est appliquée avant le démarrage du plan de contrôle de Ray sur les nœuds principaux et workers :

    sed -i 's/context\.py_executable = " "\.join(self\.nsight_cmd) + " python"/context.py_executable = " ".join(self.nsight_cmd) + f" {context.py_executable}"/g' /opt/nemo_rl_venv/lib64/python*/site-packages/ray/_private/runtime_env/nsight.py
  2. Dans nemo_rl/__init__.py (clusters locaux) : La correction est appliquée automatiquement lors de l’importation de NeMo RL, ce qui la rend transparente pour les environnements de développement et de test locaux.

Pourquoi Nous Avions Besoin des Deux Emplacements

  • ray.sub : Requis pour les clusters gérés par SLURM où les processus Ray démarrent dans des conteneurs avant que les importations Python ne se produisent. La correction doit être appliquée au niveau du système de fichiers avant l’initialisation du plan de contrôle de Ray.

  • __init__.py : Requis pour les clusters locaux et les environnements de développement où les utilisateurs démarrent directement les clusters Ray. La correction est appliquée lors de l’importation de nemo_rl, garantissant que le correctif est en place avant le démarrage de tout processus Ray.

Cette approche à deux volets garantit que le profilage Nsight fonctionne correctement, quel que soit le mode de déploiement du cluster Ray.