GNU/Linux >> Tutoriels Linux >  >> Linux

comment protéger un processeur du planificateur Linux (l'empêcher de programmer des threads sur ce processeur) ?

La réponse est d'utiliser des cpusets. L'utilitaire python cpuset facilite leur configuration.

Concepts de base

3 processeurs

  • root :présent dans toutes les configurations et contient tous les processeurs (non blindés )
  • system  :contient les processeurs utilisés pour les tâches système - celles qui doivent s'exécuter mais qui ne sont pas "importantes" (non blindées )
  • user  :contient les processeurs utilisés pour les tâches "importantes" - celles que nous voulons exécuter en mode "temps réel" (blindé )

Le shield commande gère ces 3 cpusets.

Pendant l'installation, il déplace toutes les tâches mobiles dans le cpuset non protégé (system ) et pendant le démontage, il déplace toutes les tâches mobiles dans le root cpuset.Après l'installation, la sous-commande vous permet de déplacer des tâches dans le bouclier (user ) cpuset, et en plus, pour déplacer des tâches spéciales (threads du noyau) de root à system (et donc hors du user ensemble de processeur).

Commandes :

Nous créons d'abord un bouclier. Naturellement, la disposition du bouclier dépendra de la machine/de la tâche. Par exemple, supposons que nous ayons une machine non NUMA à 4 cœurs :nous voulons dédier 3 cœurs au bouclier , et laissez 1 cœur pour les tâches sans importance; puisqu'il n'est pas NUMA, nous n'avons pas besoin de spécifier de paramètres de nœud de mémoire et nous laissons les threads du noyau s'exécuter dans le root cpuset (c'est-à-dire :sur tous les processeurs)

$ cset shield --cpu 1-3

Certains threads du noyau (ceux qui ne sont pas liés à des processeurs spécifiques) peuvent être déplacés dans le system processeur. (En général, ce n'est pas une bonne idée de déplacer les threads du noyau qui ont été liés à un processeur spécifique)

$ cset shield --kthread on

Maintenant, listons ce qui s'exécute dans le bouclier (user ) ou non blindé (system ) ensembles de processeurs :(-v pour verbeux, qui listera les noms des processus) (ajoutez un 2ème -v pour afficher plus de 80 caractères)

$ cset shield --shield -v
$ cset shield --unshield -v -v

Si nous voulons arrêter le bouclier (démontage)

$ cset shield --reset

Exécutons maintenant un processus dans le bouclier (commandes suivant '--' sont passés à la commande à exécuter, pas à cset )

$ cset shield --exec mycommand -- -arg1 -arg2

Si nous avons déjà un processus en cours d'exécution que nous voulons déplacer dans le bouclier (notez que nous pouvons déplacer plusieurs processus en passant une liste séparée par des virgules ou des plages (tout processus de la plage sera déplacé, même s'il y a des lacunes))

$ cset shield --shield --pid 1234
$ cset shield --shield --pid 1234,1236
$ cset shield --shield --pid 1234,1237,1238-1240

Concepts avancés

cset set/proc - ceux-ci vous donnent un contrôle plus fin des cpusets

Définir

Créer, ajuster, renommer, déplacer et détruire des cpusets

Commandes

Créez un cpuset, en utilisant les cpus 1-3, utilisez le nœud NUMA 1 et appelez-le "my_cpuset1"

$ cset set --cpu=1-3 --mem=1 --set=my_cpuset1

Modifiez "my_cpuset1" pour n'utiliser que les processeurs 1 et 3

$ cset set --cpu=1,3 --mem=1 --set=my_cpuset1

Détruire un cpuset

$ cset set --destroy --set=my_cpuset1

Renommer un cpuset existant

$ cset set --set=my_cpuset1 --newname=your_cpuset1

Créer un cpuset hiérarchique

$ cset set --cpu=3 --mem=1 --set=my_cpuset1/my_subset1

Lister les cpusets existants (profondeur de niveau 1)

$ cset set --list

Lister le cpuset existant et ses enfants

$ cset set --list --set=my_cpuset1

Lister tous les cpusets existants

$ cset set --list --recurse

Procéder

Gérer les threads et les processus

Commandes

Lister les tâches en cours d'exécution dans un cpuset

$ cset proc --list --set=my_cpuset1 --verbose

Exécuter une tâche dans un cpuset

$ cset proc --set=my_cpuset1 --exec myApp -- --arg1 --arg2

Déplacer une tâche

$ cset proc --toset=my_cpuset1 --move --pid 1234
$ cset proc --toset=my_cpuset1 --move --pid 1234,1236
$ cset proc --toset=my_cpuset1 --move --pid 1238-1340

Déplacer une tâche et tous ses frères

$ cset proc --move --toset=my_cpuset1 --pid 1234 --threads

Déplacer toutes les tâches d'un cpuset à un autre

$ cset proc --move --fromset=my_cpuset1 --toset=system

Déplacer les threads du noyau non épinglés dans un cpuset

$ cset proc --kthread --fromset=root --toset=system

Déplacez de force les threads du noyau (y compris ceux qui sont épinglés à un processeur spécifique) dans un cpuset (remarque :cela peut avoir des conséquences désastreuses pour le système - assurez-vous de savoir ce que vous faites)

$ cset proc --kthread --fromset=root --toset=system --force

Exemple de hiérarchie

Nous pouvons utiliser des cpusets hiérarchiques pour créer des regroupements prioritaires

  1. Créer un system cpuset avec 1 cpu (0)
  2. Créer un prio_low ensemble de processeurs avec 1 processeur (1)
  3. Créer un prio_met ensemble de processeurs avec 2 processeurs (1-2)
  4. Créer un prio_high ensemble de processeurs avec 3 processeurs (1-3)
  5. Créer un prio_all cpuset avec les 4 processeurs (0-3) (notez que c'est la même chose que root ; il est considéré comme une bonne pratique de garder une séparation avec root)

Pour atteindre ce qui précède, vous créez prio_all, puis créez un sous-ensemble prio_high sous prio_all, etc

$ cset set --cpu=0 --set=system
$ cset set --cpu=0-3 --set=prio_all
$ cset set --cpu=1-3 --set=/prio_all/prio_high
$ cset set --cpu=1-2 --set=/prio_all/prio_high/prio_med
$ cset set --cpu=1 --set=/prio_all/prio_high/prio_med/prio_low

Je peux penser à deux autres façons de le faire (mais pas aussi élégantes que cset, qui ne semble pas bénéficier d'un niveau de support fantastique de la part de Redhat) :

1) Définissez tout, y compris le PID 1 - agréable et facile (mais, apparemment - je n'ai jamais vu de problèmes moi-même - cela peut entraîner des inefficacités dans le planificateur). Le script ci-dessous (qui doit être exécuté en tant que root) exécute l'ensemble de tâches sur tous les processus en cours d'exécution, y compris init (pid 1) ; cela épinglera tous les processus en cours d'exécution à un ou plusieurs "cœurs indésirables", et en épinglant également init, cela garantira que tous les processus futurs sont également démarrés dans la liste des "cœurs indésirables" :

#!/bin/bash

if [[ -z $1 ]]; then
  printf "Usage: %s '<csv list of cores to set as junk in double quotes>'", $0
  exit -1;
fi

for i in `ps -eLfad |awk '{ print $4 } '|grep -v PID | xargs echo `; do 
   taskset -pc $1 $i;
done

2) utilisez le paramètre de noyau isolcpus (voici la documentation de https://www.kernel.org/doc/Documentation/kernel-parameters.txt):

isolcpus=   [KNL,SMP] Isolate CPUs from the general scheduler.
            Format:
            <cpu number>,...,<cpu number>
            or
            <cpu number>-<cpu number>
            (must be a positive range in ascending order)
            or a mixture
            <cpu number>,...,<cpu number>-<cpu number>

        This option can be used to specify one or more CPUs
        to isolate from the general SMP balancing and scheduling
        algorithms. You can move a process onto or off an
        "isolated" CPU via the CPU affinity syscalls or cpuset.
        <cpu number> begins at 0 and the maximum value is
        "number of CPUs in system - 1".

        This option is the preferred way to isolate CPUs. The
        alternative -- manually setting the CPU mask of all
        tasks in the system -- can cause problems and
        suboptimal load balancer performance.

J'ai utilisé ces deux mécanismes plus les cset pour plusieurs projets (d'ailleurs, veuillez pardonner l'auto-promotion flagrante :-)), je viens de déposer un brevet pour un outil appelé Pontus Vision ThreadManager qui propose des stratégies d'épinglage optimales pour tout plate-forme x86 donnée à toute charge de travail logicielle donnée ; après l'avoir testé sur un site client, j'ai obtenu de très bons résultats (réduction de 270 % des latences maximales), donc cela vaut la peine d'épingler et d'isoler le processeur.


Linux
  1. Comment rechercher sur le Web à partir d'un terminal sous Linux

  2. Comment trouver le package qui fournit un fichier spécifique sous Linux

  3. Comment calculer l'utilisation CPU d'un processus par PID sous Linux à partir de C ?

  4. Comment définir l'adresse IP de C sous Linux

  5. Comment redémarrer Linux (Ubuntu) à partir de la ligne de commande ?

Comment le noyau Linux gère les interruptions

Comment installer la dernière version d'OpenSSL à partir de la source sous Linux

Comment rechercher des fichiers à partir du terminal sous Linux

Comment trouver le nombre de cœurs de processeur à partir de la ligne de commande sous Linux

Comment obtenir le nom de fichier à partir du chemin complet sous Linux

Comment se connecter au WiFi depuis le terminal dans Ubuntu Linux