32 votes

Limitez certains processus à un pourcentage de CPU - Linux

Je rencontre le problème suivant : certains processus, générés dynamiquement, ont tendance à consommer 100% du CPU. J'aimerais limiter tous les processus correspondant à certains critères (par exemple, le nom du processus) à un certain pourcentage de CPU.

Le problème spécifique que j'essaie de résoudre est de contrôler les processus de travail folding@home. La meilleure solution à laquelle j'ai pu penser est un script perl qui s'exécute périodiquement et utilise l'utilitaire cpulimit pour limiter les processus (si vous êtes intéressé par plus de détails, consultez ce billet de blog). Ça fonctionne, mais c'est une bidouille :/

Des idées ? J'aimerais laisser la gestion des processus à l'OS :)


Merci encore pour les suggestions, mais nous ne saisissons toujours pas le point :)

La solution "ralentir" est essentiellement ce que fait l'utilitaire "cpulimit". Je dois toujours m'assurer de ralentir les processus, de tuer le processus "ralentir" une fois que le processus de travail est terminé et d'en démarrer de nouveaux pour de nouveaux processus de travail. C'est exactement ce que j'ai fait avec le script Perl et une tâche cron.

Le problème principal est que je ne sais pas à l'avance quels processus limiter. Ils sont générés dynamiquement.

Peut-être y a-t-il un moyen de limiter tous les processus d'un utilisateur à un certain pourcentage de CPU ? J'ai déjà créé un utilisateur pour exécuter les tâches folding@home, en espérant pouvoir le limiter avec le fichier /etc/security/limits.conf. Mais la limite la plus proche que j'ai pu obtenir est le temps total du CPU par utilisateur...

Ce serait bien d'avoir quelque chose qui vous permettrait de dire : "La somme de tous les pourcentages d'utilisation du CPU de ce processus utilisateur ne peut pas dépasser 50%". Et ensuite laisser les processus se battre pour ces 50% de CPU en fonction de leurs priorités...


Les gars, merci pour vos suggestions, mais ce n'est pas une question de priorités - je veux limiter le pourcentage de CPU même lorsqu'il y a beaucoup de temps CPU disponible. Les processus sont déjà à basse priorité, donc ils ne causent aucun problème de performance.

J'aimerais juste éviter que le CPU fonctionne à 100% pendant de longues périodes...

1 votes

Pourquoi est-ce une mauvaise chose? S'ils sont correctement gérés, ils ne devraient pas interférer avec d'autres processus. Ils obtiendront simplement (en effet) tous les cycles restants...

3 votes

En lisant le billet de blog, il semble qu'il veuille que les CPU aient un peu de temps d'arrêt pour ne pas trop chauffer. C'est pourquoi j'ai arrêté de faire SETI@Home - mes CPU ne duraient pas longtemps parce qu'ils chauffaient tout le temps.

0 votes

Oui, je n'ai jamais eu de problème de surchauffe avec un processeur malgré l'utilisation de SETI@Home. Et je n'ai jamais utilisé autre chose que les unités HSF standard fournies avec mes processeurs.

22voto

Datageek Points 2846

J'ai eu un problème légèrement similaire avec gzip.

Supposons que nous voulions réduire l'utilisation du processeur d'un processus gzip:

    gzip backup.tar & sleep 2 & cpulimit --limit 10 -e gzip -z

Options:

  • J'ai trouvé sleep utile car parfois cpulimit ne détectait pas immédiatement le nouveau processus gzip
  • --limit 10 limite l'utilisation du CPU de gzip à 10%
  • -z ferme automatiquement cpulimit lorsque le processus gzip se termine

Une autre option consiste à exécuter le démon cpulimit.

13voto

blabla999 Points 2316

Je ne me souviens pas et je ne pense pas qu'il y avait quelque chose de similaire dans le planificateur Unix. Vous avez besoin d'un petit programme qui contrôle les autres processus et fait ce qui suit :

boucle
    attendre pendant un certain temps tR
    envoyer SIGSTOP au processus que vous souhaitez planifier
    attendre pendant un certain temps tP
    envoyer SIGCONT au processus
boucleEnd

le ratio tR/tP contrôle la charge du CPU.


Voici une petite preuve de concept. "busy" est le programme qui utilise votre temps CPU et que vous voulez ralentir avec "slowDown" :

> cat > busy.c:
    main() { while (1) {}; }

> cc -o busy busy.c
> busy &
> top

Tâches: 192 au total,   3 en cours d'exécution, 189 en veille,   0 arrêtées,   0 zombie
Cpu(s): 76,9% us,  6,6% sy,  0,0% ni, 11,9% id,  4,5% wa,  0,0% hi,  0,0% si
Mem:   6139696k total,  6114488k utilisés,    25208k libres,   115760k buffers
Swap:  9765368k total,  1606096k utilisés,  8159272k libres,  2620712k mis en cache

  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND
26539 cg        25   0  2416  292  220 R 90,0  0,0   3:25,79 busy
...

> cat > slowDown
while true; do
 kill -s SIGSTOP $1
 sleep 0,1
 kill -s SIGCONT $1
 sleep 0,1
done

> chmod +x slowDown
> slowDown 26539 &
> top
Tâches: 200 au total,   4 en cours d'exécution, 192 en veille,   4 arrêtées,   0 zombie
Cpu(s): 48,5% us, 19,4% sy,  0,0% ni, 20,2% id,  9,8% wa,  0,2% hi,  2,0% si
Mem:   6139696k total,  6115376k utilisés,    24320k libres,    96676k buffers
Swap:  9765368k total,  1606096k utilisés,  8159272k libres,  2639796k mis en cache

  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND
26539 cg        16   0  2416  292  220 T 49,7  0,0   6:00,98 busy
...

d'accord, ce script a besoin de travailler un peu plus (par exemple, pour être interrompu et laisser le processus contrôlé continuer s'il a été arrêté à ce moment-là), mais vous comprenez le point. Je rédigerais également ce petit script en C ou similaire et calculerais le ratio CPU à partir d'un argument de ligne de commande....

cordialement

0 votes

La commande cpulimit fonctionne de cette manière. Elle surveille les processus que vous avez définis. Si un processus utilise plus que la limite, il suspend le processus. - Vous pouvez consulter le code source sur Github.

8voto

elGEoRgE TheKiLLa Points 470

Je pense que sous Linux, il n'y a pas de solution pour plafonner l'utilisation du processeur, mais il existe un moyen acceptable de limiter tout processus à une certaine utilisation du processeur : http://ubuntuforums.org/showthread.php?t=992706

Au cas où ils supprimeraient l'info, voici à nouveau l'info


  1. INSTALLER LES PAQUETS

  2. Installer le paquet cpulimit. Code :

    sudo apt-get install cpulimit

  3. Installer le paquet gawk. Code :

    sudo apt-get install gawk

  4. CRÉER LE FICHIER DU DÉMON CPULIMIT

Ouvrez un éditeur de texte avec des privilèges Root et sauvegardez le texte du daemon script ci-dessous dans un nouveau fichier /usr/bin/cpulimit_daemon.sh.

Code :

#!/bin/bash
# ==============================================================
# CPU limit daemon - set PID's max. percentage CPU consumptions
# ==============================================================

# Variables
CPU_LIMIT=20        # Maximum percentage CPU consumption by each PID
DAEMON_INTERVAL=3   # Daemon check interval in seconds
BLACK_PROCESSES_LIST=   # Limit only processes defined in this variable. If variable is empty (default) all violating processes are limited.
WHITE_PROCESSES_LIST=   # Limit all processes except processes defined in this variable. If variable is empty (default) all violating processes are limited.

# Check if one of the variables BLACK_PROCESSES_LIST or WHITE_PROCESSES_LIST is defined.
if [[ -n "$BLACK_PROCESSES_LIST" &&  -n "$WHITE_PROCESSES_LIST" ]] ; then    # If both variables are defined then error is produced.
   echo "At least one or both of the variables BLACK_PROCESSES_LIST or WHITE_PROCESSES_LIST must be empty."
   exit 1
elif [[ -n "$BLACK_PROCESSES_LIST" ]] ; then                                 # If this variable is non-empty then set NEW_PIDS_COMMAND variable to bellow command
   NEW_PIDS_COMMAND="top -b -n1 -c | grep -E '$BLACK_PROCESSES_LIST' | gawk '\$9>CPU_LIMIT {print \$1}' CPU_LIMIT=$CPU_LIMIT"
elif [[ -n "$WHITE_PROCESSES_LIST" ]] ; then                                 # If this variable is non-empty then set NEW_PIDS_COMMAND variable to bellow command
   NEW_PIDS_COMMAND="top -b -n1 -c | gawk 'NR>6' | grep -E -v '$WHITE_PROCESSES_LIST' | gawk '\$9>CPU_LIMIT {print \$1}' CPU_LIMIT=$CPU_LIMIT"
else
   NEW_PIDS_COMMAND="top -b -n1 -c | gawk 'NR>6 && \$9>CPU_LIMIT {print \$1}' CPU_LIMIT=$CPU_LIMIT"
fi

# Search and limit violating PIDs
while sleep $DAEMON_INTERVAL
do
   NEW_PIDS=$(eval "$NEW_PIDS_COMMAND")                                                                    # Violating PIDs
   LIMITED_PIDS=$(ps -eo args | gawk '$1=="cpulimit" {print $3}')                                          # Already limited PIDs
   QUEUE_PIDS=$(comm -23 <(echo "$NEW_PIDS" | sort -u) <(echo "$LIMITED_PIDS" | sort -u) | grep -v '^$')   # PIDs in queue

   for i in $QUEUE_PIDS
   do
       cpulimit -p $i -l $CPU_LIMIT -z &   # Limit new violating processes
   done
done
  1. MODIFIER LES VARIABLES EN FONCTION DES BESOINS DE VOTRE ENVIRONNEMENT

CPU_LIMIT Changez cette variable dans le script ci-dessus si vous souhaitez que la consommation du CPU pour chaque processus soit inférieure à 20%. Veuillez lire le chapitre "Si vous utilisez un ordinateur SMP" ci-dessous si vous avez un ordinateur SMP (plus d'un CPU ou un CPU avec plus d'un cœur).

DAEMON_INTERVAL Changez cette variable dans le script ci-dessus si vous souhaitez avoir des vérifications plus ou moins régulières. L'intervalle est en secondes et la valeur par défaut est de 3 secondes.

BLACK_PROCESS_LIST et WHITE_PROCESSES_LIST La variable BLACK_PROCESSES_LIST limite uniquement les processus spécifiés. Si la variable est vide (par défaut), tous les processus en infraction sont limités.

La variable WHITE_PROCESSES_LIST limite tous les processus sauf ceux définis dans cette variable. Si la variable est vide (par défaut), tous les processus en infraction sont limités.

L'une ou les deux variables BLACK_PROCESSES_LIST et WHITE_PROCESSES_LIST doivent être vides - il n'est pas logique que les deux variables soient définies.

Vous pouvez spécifier plusieurs processus dans l'une de ces deux variables en utilisant les caractères de délimitation "|" (sans guillemets doubles). Exemple : si vous souhaitez cpulimiter tous les processus sauf ceux de mysql, firefox et gedit, définissez la variable : WHITE_PROCESSES_LIST="mysql|firefox|gedit"

  1. PROCÉDURE POUR DÉMARRER AUTOMATIQUEMENT LE DÉMON AU DÉMARRAGE

  2. Définir les autorisations de fichiers pour l'utilisateur Root : Code :

    sudo chmod 755 /usr/bin/cpulimit_daemon.sh

  3. Ouvrez un éditeur de texte avec les privilèges de Root et enregistrez le script ci-dessous dans le nouveau fichier /etc/init.d/cpulimit.

Code :

#!/bin/sh
#
# Script to start CPU limit daemon
#
set -e

case "$1" in
start)
if [ $(ps -eo pid,args | gawk '$3=="/usr/bin/cpulimit_daemon.sh"  {print $1}' | wc -l) -eq 0 ]; then
    nohup /usr/bin/cpulimit_daemon.sh >/dev/null 2>&1 &
    ps -eo pid,args | gawk '$3=="/usr/bin/cpulimit_daemon.sh"  {print}' | wc -l | gawk '{ if ($1 == 1) print " * cpulimit daemon started successfully"; else print " * cpulimit daemon can not be started" }'
else
    echo " * cpulimit daemon can't be started, because it is already running"
fi
;;
stop)
CPULIMIT_DAEMON=$(ps -eo pid,args | gawk '$3=="/usr/bin/cpulimit_daemon.sh"  {print $1}' | wc -l)
CPULIMIT_INSTANCE=$(ps -eo pid,args | gawk '$2=="cpulimit" {print $1}' | wc -l)
CPULIMIT_ALL=$((CPULIMIT_DAEMON + CPULIMIT_INSTANCE))
if [ $CPULIMIT_ALL -gt 0 ]; then
    if [ $CPULIMIT_DAEMON -gt 0 ]; then
        ps -eo pid,args | gawk '$3=="/usr/bin/cpulimit_daemon.sh"  {print $1}' | xargs kill -9   # kill cpulimit daemon
    fi

    if [ $CPULIMIT_INSTANCE -gt 0 ]; then
        ps -eo pid,args | gawk '$2=="cpulimit" {print $1}' | xargs kill -9                    # release cpulimited process to normal priority
    fi
    ps -eo pid,args | gawk '$3=="/usr/bin/cpulimit_daemon.sh"  {print}' | wc -l | gawk '{ if ($1 == 1) print " * cpulimit daemon can not be stopped"; else print " * cpulimit daemon stopped successfully" }'
else
    echo " * cpulimit daemon can't be stopped, because it is not running"
fi
;;
restart)
$0 stop
sleep 3
$0 start
;;
status)
ps -eo pid,args | gawk '$3=="/usr/bin/cpulimit_daemon.sh"  {print}' | wc -l | gawk '{ if ($1 == 1) print " * cpulimit daemon is running"; else print " * cpulimit daemon is not running" }'
;;
esac
exit 0
  1. Changez le propriétaire du fichier en Root :

Code :

sudo chown root:root /etc/init.d/cpulimit
  1. Modifier les autorisations :

Code :

sudo chmod 755 /etc/init.d/cpulimit
  1. Ajouter script aux répertoires de la procédure de démarrage : Code :

    sudo update-rc.d cpulimit defaults

  2. Redémarrer pour vérifier si script lance le démon cpulimit au démarrage : Code :

    sudo reboot

  3. VÉRIFIER, ARRÊTER, DÉMARRER ET REDÉMARRER MANUELLEMENT LE DÉMON

Note : Daemon et service dans ce tutoriel ont la même signification.

Note : Pour les utilisateurs utilisant une version antérieure à Ubuntu 8.10 (comme Ubuntu 8.04 LTS), au lieu de la commande service, utilisez la syntaxe "sudo /etc/init.d/cpulimit status/start/stop/restart" ou installez le paquet sysvconfig en utilisant la commande : sudo apt-get install sysvconfig

Vérifier si le service cpulimit est en cours d'exécution Vérifier les retours de commande : "cpulimit daemon is running" si le service est lancé, ou "cpulimit daemon is not running" si le service n'est pas lancé. Code :

sudo service cpulimit status

Démarrer le service cpulimit Vous pouvez démarrer manuellement le démon cpulimit qui commencera à omettre la consommation du CPU. Code :

sudo service cpulimit start

Arrêter le service cpulimit La commande Stop arrête le démon cpulimit (donc aucun nouveau processus ne sera limité) et permet également à tous les processus limités existants d'avoir un accès complet au CPU, comme c'était le cas avant que cpulimit ne fonctionne. Code :

sudo service cpulimit stop

Redémarrer le service cpulimit Si vous modifiez les paramètres de certaines variables dans /usr/bin/cpulimit_daemon.sh comme CPU_LIMIT, DAEMON_INTERVAL, BLACK_PROCESSES_LIST ou WHITE_PROCESSES_LIST, alors après avoir modifié les paramètres vous devez redémarrer le service. Code :

sudo service cpulimit restart
  1. VÉRIFIER LA CONSOMMATION DE CPU AVEC OU SANS LE DÉMON CPULIMIT

Sans démon 1. arrêter le démon cpulimit (sudo service cpulimit stop) 2. exécutez des tâches gourmandes en CPU en arrière-plan 3. Exécutez la commande : top et vérifiez la colonne %CPU. Le résultat de %CPU est probablement supérieur à 20% pour chaque processus.

Avec le démon activé 1. démarrez le démon cpulimit (sudo service cpulimit start) 2. Exécutez les mêmes tâches intensives en arrière-plan. 3. exécutez la commande : top et vérifiez la colonne %CPU. Le résultat de %CPU doit être de 20% maximum pour chaque processus. Note : N'oubliez pas qu'au début, %CPU peut être supérieur à 20%, car le démon doit attraper les processus en infraction dans un intervalle de 3 secondes (défini dans script par défaut).

  1. SI UTILISATION D'ORDINATEUR SMP

J'ai testé ce code sur un ordinateur Intel à processeur double cœur - qui se comporte comme un ordinateur SMP. N'oubliez pas que la commande top et aussi cpulimit par défaut se comportent en mode Irix, où 20% signifie 20% d'un CPU. S'il y a deux CPU (ou dual-core), le %CPU total peut être de 200%. Dans la commande top, le mode Irix peut être désactivé avec la commande I (en appuyant sur +i lorsque la commande top est en cours d'exécution) et le mode Solaris est activé, où la quantité totale de CPU est divisée par le nombre de CPU, de sorte que %CPU ne peut être supérieur à 100% sur n'importe quel nombre de CPU. Veuillez lire plus d'informations sur la commande top dans la page de manuel top (recherchez la commande I). Veuillez également lire plus d'informations sur le fonctionnement de cpulimit sur les ordinateurs SMP sur la page officielle de cpulimit.

Mais comment fonctionne le démon cpulimit sur un ordinateur SMP ? Toujours en mode Irix. Ainsi, si vous souhaitez dépenser 20% de la puissance du processeur sur un ordinateur à 2 CPU, alors 40% doit être utilisé pour la variable CPU_LIMIT dans le daemon cpulimit script.

  1. DÉSINSTALLER LE DÉMON CPULIMIT ET LE PROGRAMME CPULIMIT

Si vous souhaitez vous débarrasser de cpulimit daemon, vous pouvez nettoyer votre système en supprimant cpulimit daemon et en désinstallant le programme cpulimit.

  1. Arrêter le démon cpulimit Code :

    sudo service cpulimit stop # Stop cpulimit daemon and all cpulimited processes

  2. Supprimer le daemon de la procédure de démarrage Code :

    sudo update-rc.d -f cpulimit remove # Suppression des liens symboliques

  3. Supprimer la procédure de démarrage Code :

    sudo rm /etc/init.d/cpulimit # Supprimer cpulimit boot-up script

  4. Supprimer le démon cpulimit Code :

    sudo rm /usr/bin/cpulimit_daemon.sh # Supprimer le démon cpulimit script

  5. Désinstaller le programme cpulimit Code :

    sudo apt-get remove cpulimit

  6. Désinstaller le programme gawk Si vous n'avez pas besoin de ce programme pour un autre script, vous pouvez le mettre à distance. Code :

    sudo apt-get remove gawk

  7. NOTE SUR LES AUTEURS

Je viens d'écrire un démon pour cpulimit (scripts bash ci-dessus). Je ne suis pas l'auteur du projet cpulimit. Si vous avez besoin de plus d'informations sur le programme cpulimit, veuillez lire la page web officielle de cpulimit : http://cpulimit.sourceforge.net/ .

Regards, Abcuser

0 votes

Il y a une solution pour limiter l'utilisation, voir: bash -c "help ulimit"

0 votes

Loi d'un solide, mais ça fonctionne plus ou moins. Dans mon cas, ça perturberait le tty si j'utilisais top, ça disait qu'il ne fonctionnait pas alors que c'était le cas, mais sinon ça faisait le travail. Merci beaucoup!

3 votes

Ulimit n'est pas une solution pour limiter %

6voto

Kibbee Points 36474

Pourquoi limiter le pourcentage du processeur alors que vous pouvez simplement ajuster la priorité du processus en utilisant renice? En utilisant renice et en définissant une priorité basse, le processus peut toujours utiliser 100% du processeur s'il est disponible, mais tout autre processus ayant une priorité plus élevée obtiendra le processus lorsqu'il en aura besoin, avec presque aucun délai perceptible.

4voto

yapa Points 21

J'ai rencontré un problème similaire, et les autres solutions présentées dans le fil de discussion ne l'abordent pas du tout. Ma solution fonctionne pour l'instant, mais elle est suboptimale, notamment dans les cas où le processus est détenu par root.
Mon contournement pour le moment est de m'efforcer de m'assurer de ne pas avoir de processus longs détenus par root (comme par exemple, que les sauvegardes soient effectuées uniquement en tant qu'utilisateur)

Je viens d'installer l'applet de capteurs matériels pour gnome, et d'établir des alarmes pour les températures élevées et basses du CPU, puis de configurer les commandes suivantes pour chaque alarme:

Basse:

mv /tmp/hogs.txt /tmp/hogs.txt.$$ && cat /tmp/hogs.txt.$$ | xargs -n1 kill -CONT

Haute:

touch /tmp/hogs.txt && ps -eo pcpu,pid | sort -n -r | head -1 | gawk '{ print $2 }' >> /tmp/hogs.txt && xargs -n1 kill -STOP < /tmp/hogs.txt

La bonne nouvelle est que mon ordinateur ne surchauffe plus et ne plante plus. L'inconvénient est que les processus de terminal se déconnectent du terminal lorsqu'ils sont arrêtés, et ne sont pas reconnectés lorsqu'ils reçoivent le signal CONT. L'autre chose est que si c'était un programme interactif qui a provoqué la surchauffe (comme un certain plugin de navigateur web!), alors il va se figer en plein milieu de ce que je fais en attendant que le CPU refroidisse. Ce serait mieux que la gestion de l'échelle de CPU s'occupe de cela au niveau global, mais le problème est que je n'ai que deux réglages sélectionnables sur mon CPU et le réglage lent n'est pas assez lent pour éviter la surchauffe.

Juste pour réitérer ici, cela n'a rien du tout à voir avec la priorité des processus, le renicage, et évidemment rien à voir avec l'arrêt des tâches qui s'exécutent longtemps. Cela concerne la prévention de l'utilisation du CPU à 100% pendant trop longtemps, car le matériel n'est pas capable de dissiper rapidement la chaleur lorsqu'il fonctionne à pleine capacité (un CPU inactif génère moins de chaleur qu'un CPU chargé à pleine charge).

D'autres possibilités évidentes qui pourraient aider sont:

Réduire la vitesse du CPU dans le BIOS

Remplacer le dissipateur de chaleur ou réappliquer le gel thermique pour voir si cela aide

Nettoyer le dissipateur de chaleur avec de l'air comprimé

Remplacer le ventilateur du CPU

[edit] Note: plus de surchauffe à 100% de CPU lorsque je désactive la vitesse du ventilateur variable dans le bios (asus p5q pro turbo). Avec le CPU complètement chargé, chaque cœur atteint 49 degrés Celsius.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X