Comprendre l'affinité CPU et définir la priorité des processus avec nice et renice
Dans le domaine de l'administration système Linux, l'optimisation des performances est un effort continu. Deux techniques fondamentales que les administrateurs système exploitent à cette fin sont la gestion de l'affinité CPU et l'ajustement des priorités des processus. L'affinité CPU, souvent appelée liaison CPU (CPU binding), vous permet de diriger un processus pour qu'il s'exécute sur des cœurs de processeur spécifiques. Cela peut considérablement améliorer les performances en réduisant la surcharge de commutation de contexte et en améliorant l'utilisation du cache. À cela s'ajoute la possibilité de contrôler la quantité de temps CPU qu'un processus est autorisé à consommer par rapport aux autres, ce qui est réalisé grâce à la gestion de la priorité des processus à l'aide de commandes telles que nice et renice. Cet article explorera ces deux concepts, fournissant des conseils pratiques sur leur mise en œuvre et leurs avantages.
Comprendre ces outils permet aux administrateurs d'affiner le comportement du système, garantissant que les applications critiques reçoivent des ressources adéquates tout en empêchant les processus incontrôlables d'affecter la stabilité globale du système. Que vous résolviez des goulots d'étranglement de performance, configuriez des environnements de calcul haute performance, ou cherchiez simplement un système plus réactif, maîtriser l'affinité CPU et la priorité des processus est une compétence essentielle.
Affinité CPU : Lier les processus à des cœurs spécifiques
L'affinité CPU est un mécanisme qui permet au système d'exploitation d'associer un processus ou un thread à un CPU spécifique ou à un ensemble de CPUs. Lorsqu'un processus est lié à un cœur de processeur, il ne s'exécutera que sur ce cœur. Cela a plusieurs implications en matière de performance :
- Réduction de l'invalidation du cache : Les CPU modernes disposent de caches à plusieurs niveaux (L1, L2, L3) qui stockent les données fréquemment consultées. Lorsqu'un processus migre entre différents cœurs de processeur, ses données dans le cache du cœur précédent deviennent invalides, et de nouvelles données doivent être récupérées pour le nouveau cœur. Lier un processus à un seul cœur garantit que ses données restent dans le cache de ce cœur, ce qui entraîne des temps d'accès plus rapides.
- Minimisation de la commutation de contexte : Lorsque le planificateur décide d'exécuter un processus différent sur un cœur, l'état du processus en cours est enregistré (commutation de contexte) et l'état du nouveau processus est chargé. Si un processus se déplace fréquemment entre les cœurs, la surcharge associée à ces commutations de contexte peut s'accumuler. L'affinité CPU peut réduire cette surcharge en maintenant le processus sur le même cœur.
- Architectures NUMA : Dans les systèmes à accès mémoire non uniforme (NUMA), les temps d'accès à la mémoire varient en fonction du cœur du processeur et de sa proximité avec le contrôleur mémoire. Lier un processus à un cœur spécifique peut également garantir qu'il accède à la mémoire locale, réduisant ainsi la latence.
Comment définir l'affinité CPU
Bien que le noyau Linux gère souvent l'affinité CPU automatiquement, les administrateurs peuvent l'influencer manuellement. L'outil principal pour cela est taskset.
Utilisation de taskset
La commande taskset vous permet de récupérer ou de définir un masque d'affinité CPU pour un processus en cours d'exécution ou de lancer une nouvelle commande avec une affinité spécifiée.
Syntaxe :
-
Pour visualiser l'affinité CPU d'un processus en cours d'exécution :
bash taskset -p <PID> -
Pour définir l'affinité CPU d'un processus en cours d'exécution :
bash taskset -p <mask> <PID>
Le<mask>est un nombre hexadécimal représentant un masque de bits des CPUs autorisés. Par exemple,0x1(binaire0001) signifie CPU 0,0x2(binaire0010) signifie CPU 1,0x3(binaire0011) signifie CPUs 0 et 1, et ainsi de suite. -
Pour lancer une nouvelle commande avec une affinité CPU spécifique :
bash taskset -c <cpu_list> <command>
La<cpu_list>est une liste d'identifiants de CPU ou de plages séparés par des virgules (par exemple,0,0-3,1,3).
Exemple :
Supposons que vous souhaitiez exécuter une tâche de calcul my_program et la lier au cœur de CPU 3 :
taskset -c 3 ./my_program
Si my_program est déjà en cours d'exécution avec le PID 12345, et que vous souhaitez le déplacer exclusivement vers le cœur de CPU 1 :
taskset -p 1 12345
Astuce : Vous pouvez déterminer le nombre de CPUs disponibles en utilisant nproc ou en inspectant /proc/cpuinfo.
Avertissement : Définir incorrectement l'affinité CPU peut entraîner une dégradation des performances. Il est préférable de tester votre application avec et sans les paramètres d'affinité pour confirmer les avantages.
Gestion de la priorité des processus avec nice et renice
Alors que l'affinité CPU détermine où un processus s'exécute, la priorité du processus détermine quelle quantité de temps CPU il reçoit par rapport aux autres processus. Linux utilise un concept de « gentillesse » (niceness) pour contrôler la priorité d'ordonnancement. La valeur de gentillesse va de -20 (priorité la plus élevée, le plus de temps CPU) à +19 (priorité la plus basse, le moins de temps CPU). La gentillesse par défaut pour les processus est de 0.
Une valeur de gentillesse plus élevée signifie que le processus est plus « gentil » envers les autres processus, leur cédant plus de temps CPU. Inversement, une valeur de gentillesse plus faible signifie que le processus est moins « gentil » et essaiera de capter plus de temps CPU.
La commande nice
La commande nice est utilisée pour exécuter un programme avec un niveau de gentillesse modifié. Elle est généralement utilisée lors du lancement d'un nouveau processus.
Syntaxe :
nice -n <niceness_level> <command>
-n <niceness_level>: Spécifie la valeur de gentillesse (la valeur par défaut est 10 si non spécifiée).
Exemple :
Pour exécuter my_background_task avec une faible priorité (valeur de gentillesse élevée de 15) :
nice -n 15 my_background_task
Pour exécuter my_critical_app avec une priorité élevée (valeur de gentillesse faible de -10) :
nice -n -10 my_critical_app
Note importante : Seul l'utilisateur root peut attribuer une valeur de gentillesse négative (augmenter la priorité). Les utilisateurs réguliers ne peuvent augmenter que la valeur de gentillesse (diminuer la priorité) de leurs propres processus.
La commande renice
La commande renice est utilisée pour modifier le niveau de gentillesse d'un ou plusieurs processus déjà en cours d'exécution.
Syntaxe :
renice -n <niceness_level> -p <PID>
-n <niceness_level>: La nouvelle valeur de gentillesse.-p <PID>: L'identifiant du processus (PID) du ou des processus à modifier.
Exemple :
Pour diminuer la priorité (augmenter la gentillesse) du processus 12345 à 10 :
renice -n 10 -p 12345
Pour augmenter la priorité (diminuer la gentillesse) du processus 54321 à -5 (nécessite les privilèges root) :
sudo renice -n -5 -p 54321
renice peut également cibler des processus par utilisateur (-u) ou par groupe de processus (-g).
Exemple :
Pour définir tous les processus appartenant à l'utilisateur www-data à une gentillesse de 5 :
sudo renice -n 5 -u www-data
Astuce : Utilisez top ou htop pour visualiser la valeur de gentillesse (colonne NI) des processus en cours d'exécution et identifier les candidats à l'ajustement de priorité.
Avertissement : Donner à un processus une priorité très élevée (valeur de gentillesse faible) peut affamer les autres processus et rendre le système non réactif. Utilisez avec prudence, en particulier sur les systèmes de production.
Scénarios pratiques et meilleures pratiques
Scénarios d'affinité CPU :
- Serveurs de bases de données : Lier les processus de base de données à des cœurs spécifiques peut améliorer les performances des requêtes en garantissant que les données restent dans le cache du CPU.
- Applications de trading haute fréquence : Celles-ci exigent souvent une latence minimale et des performances prévisibles, ce qui rend la liaison CPU cruciale.
- Hôtes de virtualisation : Pour dédier des cœurs spécifiques aux machines virtuelles ou à l'hôte lui-même, améliorant ainsi l'isolation et les performances.
Scénarios de priorité des processus :
- Tâches par lots/Tâches d'arrière-plan : Celles-ci peuvent être exécutées avec une valeur de gentillesse élevée (
nice -n 15) afin de ne pas interférer avec les tâches utilisateur interactives ou les services critiques. - Applications interactives : Garantir que les applications de bureau ou les shells restent réactifs en empêchant les tâches d'arrière-plan de consommer toutes les ressources CPU.
- Allocation de ressources d'urgence : Dans de rares cas, si un processus système critique rencontre des difficultés, sa priorité peut être temporairement augmentée à l'aide de
renice(en tant que root).
Meilleures pratiques :
- Tester d'abord : Mesurez toujours les performances avant et après l'application des changements d'affinité CPU ou de priorité. Les gains ne sont pas toujours garantis et peuvent dépendre de l'application.
- Comprendre votre matériel : Soyez conscient de la topologie de votre CPU (cœurs, sockets, nœuds NUMA) lors de la définition de l'affinité CPU.
- Utiliser
top/htop: Surveillez l'utilisation du CPU, les valeurs de gentillesse et les états des processus pour identifier les problèmes de performance et tester les changements. - Privilèges root pour l'augmentation de priorité : N'oubliez que seul root peut diminuer la valeur de gentillesse (augmenter la priorité). Utilisez ce pouvoir judicieusement.
- Commencer prudemment : Pour les ajustements de priorité, commencez par des valeurs de gentillesse modérées (par exemple, 5, 10) avant d'aller aux extrêmes (-20 ou +19).
- Considérer la conscience NUMA : Pour les systèmes NUMA, des outils comme
numactloffrent un contrôle plus avancé sur la liaison du CPU et de la mémoire.
Conclusion
L'affinité CPU et la priorité des processus sont de puissants outils dans l'arsenal de l'administrateur système Linux pour le réglage des performances. En liant stratégiquement les processus à des cœurs de CPU spécifiques à l'aide de taskset, vous pouvez optimiser l'utilisation du cache et réduire la commutation de contexte. En ajustant les priorités des processus avec nice et renice, vous pouvez garantir que les applications critiques reçoivent les ressources CPU dont elles ont besoin, tandis que les tâches moins importantes s'exécutent en arrière-plan sans affecter la réactivité du système. L'utilisation efficace de ces techniques nécessite une compréhension de vos charges de travail, de votre matériel et des tests minutieux, mais les avantages en termes de performance et de stabilité du système peuvent être substantiels.