dimanche 14 septembre 2014

Compiler ou faire un traitement consommateur (ex; audio/vidéo) sans trop faire chauffer son ordinateur (portable)

Pour accéder à la Liste des articles de ce blog c'est par ici

Bonjour,

aujourd'hui je vous parle d'un soucis que vous avez peut-être déjà rencontré pendant une compilation  ou autre traitement audio/vidéo : la surchauffe de l'ordinateur et l'extinction des feux ...

Ce problème est particulièrement courant sur les ordinateurs portables qui ont tendance à beaucoup chauffer !

Si vous voulez préserver votre ordinateur mais que vous voulez quand même compiler et utiliser vos logiciels de traitement audio/vidéo sans trop le stresser, cet article est fait pour vous.

Monitoring de la température


Prérequis

Installer le package debian lm-sensors qui permet d'obtenir la température des CPUs et qui est utilisé par les scripts ci-dessous:
$ sudo apt-get install lm-sensors ubuntu-sounds vorbis-tools jack-tools

Principe de l'astuce

En général, les compilateurs utilisés sont gcc et g++ mais ce principe peut s'appliquer à d'autre compilateur. Nous allons écrire des scripts gcc et g++ qui remplaceront aux yeux du système les vrais programmes gcc et g++. Ce sont juste des wrappers qui attenderont que la température des cpus diminuent avant de lancer la compilation suivante.

tout d'abord, créez un répertoire bin dans votre répertoire utilisateur:
$ mkdir ~/bin

Puis éditer les deux scripts à créer:
$ gedit ~/bin/gcc ~/bin/g++

Contenu du script gcc :
#!/bin/bash
white='\e[1;37m'
NC='\e[0m'

MAX_TEMP="70"

temp() {
  sensors | grep "Core[ 0-9]*:" | sed -e 's/.*\([+-][0-9.]\+\)°C.*(.*$/\1/' | sort -n -r | head -n 1 | sed -e 's/-[0-9.]\+/0/;s/+//'
}


CURRENT_TEMP=$(temp)
TOO_HOT=0
# now wait for it to cool down...
while [ $(echo "$CURRENT_TEMP > $MAX_TEMP" | bc) = 1 ]; do
    [ $TOO_HOT == 0 ] && echo -e "${white} CPU temp $CURRENT_TEMP ${NC}"
    TOO_HOT=1
    sleep 10
    CURRENT_TEMP=$(temp)
done

[ $TOO_HOT == "1" ] && echo -e "${white} CPU was too hot : ok now, restarting...${NC}"

/usr/bin/gcc $@

Contenu du script g++  (la même chose que précédemment mais la commande à lancer est g++):
#!/bin/bash
white='\e[1;37m'
NC='\e[0m'

MAX_TEMP="70"

temp() {
  sensors | grep "Core[ 0-9]*:" | sed -e 's/.*\([+-][0-9.]\+\)°C.*(.*$/\1/' | sort -n -r | head -n 1 | sed -e 's/-[0-9.]\+/0/;s/+//'
}


CURRENT_TEMP=$(temp)
TOO_HOT=0
# now wait for it to cool down...
while [ $(echo "$CURRENT_TEMP > $MAX_TEMP" | bc) = 1 ]; do
    [ $TOO_HOT == 0 ] && echo -e "${white} CPU temp $CURRENT_TEMP ${NC}"
    TOO_HOT=1
    sleep 10
    CURRENT_TEMP=$(temp)
done

[ $TOO_HOT == "1" ] && echo -e "${white} CPU was too hot : ok now, restarting...${NC}"

/usr/bin/g++ $@


Rendez les scripts exécutables:
$ chmod 755 ~/bin/gcc ~/bin/g++

Mettre en avant du PATH les scripts créés: Pour cela modifiez votre ~/.profile:
Pour éditer le fichier:
$ gedit ~/.profile

Ajouter à la fin du fichier la ligne suivante:
export PATH=~/bin:$PATH

Généralisation

Voici un autre script : script qui démarre un programme utilisateur et surveille la température des CPUs. si la température dépasse le seuil MAX_TEMP alors le programme utilisateur est arrêté (pause) puis lorsque la température descend, le process est réactivé (continue).

Son utilisation:
mon_cpu_too_hot.sh COMMAND
Exemple:
$ mon_cpu_too_hot.sh cp -r / /Backup

Pour les applications audio sous jack:
mon_cpu_too_hot.sh -j COMMAND
Exemple:
$ mon_cpu_too_hot.sh -j ardour3

Voici le contenu du script:
#!/bin/bash
white='\e[1;37m'
NC='\e[0m'

MAX_TEMP="80"

HANDLE_JACKAUDIO=0
export JACK_PLAY_CONNECT_TO="system:playback_%d"

jack_bell() {
  jack.play /usr/share/sounds/ubuntu/stereo/bell.ogg
  jack.play /usr/share/sounds/ubuntu/stereo/bell.ogg
  jack.play /usr/share/sounds/ubuntu/stereo/bell.ogg
}

temp() {
  sensors | grep "Core[ 0-9]*:" | sed -e 's/.*\([+-][0-9.]\+\)°C.*(.*$/\1/' | sort -n -r | head -n 1 | sed -e 's/-[0-9.]\+/0/;s/+//'
}

stop_process_and_childs() {
      kill -STOP $1
      ps -o pid --no-headers --ppid $1 | 
      while read CPID
      do
        kill -STOP $CPID
      done
}

continue_process_and_childs() {
      ps -o pid --no-headers --ppid $1 | 
      while read CPID
      do
        kill -CONT $CPID
      done
      kill -CONT $1
}

jackd_stop() {
  pkill -STOP jackdbus
}

jackd_continue() {
  pkill -CONT jackdbus
}

if [ "$1" == "-j" ]; then
  HANDLE_JACKAUDIO=1
  shift
fi

COMMAND="$1"
shift

"$COMMAND" "$@" &

PID=$!

echo -e "${white}CPU temp max $MAX_TEMP : control PPID $PID ${NC}"

while [ "$(ps -p $PID --no-header)" != "" ]
do
  CURRENT_TEMP=$(temp)
  TOO_HOT=0
  sleep 3
  while [ $(echo "$CURRENT_TEMP > $MAX_TEMP" | bc) = 1 ]; do
    if [ $TOO_HOT == 0 ]; then
       echo -e "${white} CPU temp $CURRENT_TEMP : STOPPING PROCESS $PID and its childs ${NC}"
 #     ogg123 -d pulse -y 3 /usr/share/sounds/ubuntu/stereo/bell.ogg 2> /dev/null
       [ $HANDLE_JACKAUDIO == 1 ] && jack_bell
    fi
    TOO_HOT=1
      [ $HANDLE_JACKAUDIO == 1 ] && jackd_stop
      stop_process_and_childs $PID
      sleep 10
      CURRENT_TEMP=$(temp)
  done

  if [ $TOO_HOT == 1 ]; then
    echo -e "${white} CPU was too hot : ok now, restarting...${NC}"
    continue_process_and_childs $PID
    [ $HANDLE_JACKAUDIO == 1 ] && jackd_continue
  fi
done

Si vous ne voulez rien changer à vos habitudes, vous pouvez créer des alias qui appelleront automatiquement ce script (dans le fichier ~/.bashrc):
alias del='mon_cpu_too_hot.sh /usr/bin/trash-put'
alias rsync='mon_cpu_too_hot.sh /usr/bin/rsync'
alias cp='mon_cpu_too_hot.sh /bin/cp'
alias mv='mon_cpu_too_hot.sh /bin/mv'
alias rm='mon_cpu_too_hot.sh /bin/rm'
alias ardour3='mon_cpu_too_hot.sh -j /usr/local/bin/ardour3'
...

Si vous voulez utiliser ces alias avec la commande sudo, il vous faudra ajouter l'alias suivant pour cela fonctionne:
alias sudo='sudo '

NB: l'espace est important !


Toutes ces opérations seront dorénavant soucieuse de la température de votre CPU ! Notez l'option -j qui arrête également le serveur de son jack lorsque c'est nécessaire.

Attention, ce script ne fonctionne pas avec les commandes en ligne interactive (comme 'rm -i').

Si vous voulez utiliser des interfaces graphiques avec ce script (comme ardour3), démarrez le logiciel à partir d'un terminal comme cela vous pourrez voir les messages de ce script (en gras et blanc).

Si vous avez une carte son avec pulseaudio sur votre ordinateur, vous pourrez émettre un son de votre choix lorsque le CPU est trop chaud et qu'un programme est mis en pause: (décommentez la ligne suivante dans le script ci-dessus)

ogg123 -d pulse -y 3 /usr/share/sounds/ubuntu/stereo/bell.ogg 2> /dev/null

Tuner votre script ...

La variable MAX_TEMP représente la température maximum à ne pas dépasser. Vous pouvez tuner ce paramètre à votre guise. (Prenez une valeur moins élevé que la température critique de votre CPU: Pour la connaître tapez: $ sensors).

La ligne "sleep 10" fait attendre le programme pendant 10s. Si ce n'est pas suffisant pour refroidir le CPU, vous pouvez augmenter le nombre de secondes ...

Les scripts gcc et g++ rendront fatalement la compilation beaucoup plus longue qu'à pleine puissance mais vous arriverez au bout sans problème.

Sinon, sur des programmes nécessitant beaucoup de puissance de calcul (faisant donc chauffer l'ordinateur: traitement audio/vidéo e.g. ardour, ffmpeg; avconv, lame, oggconvert, ...), le troisième script (e.g mon_cpu_too_hot.sh) sera d'une aide précieuse pour éviter l'extinction intempestive de votre ordinateur ...

Enfin, si malgré cela, votre ordinateur continue à s'éteindre rapidement, scrutez les processus consommateur avec la commande top et vérifiez si ils sont pertinents, Sinon, pensez à faire réviser votre ordinateur - souvent un dépoussiérage de l'intérieur suffira (CPU / ventilateur).

Alternative : Limiter l'utilisation du CPU par un process

Vous pouvez aussi utiliser cpulimit qui permet de limiter l'utilisation du CPU à un certain pourcentage de puissance CPU. 

Cette commande utilise aussi les signaux STOP et CONT pour mettre en pause et faire repartir le processus visé par la commande de tel façon à ce qu'il n'utilise pas plus que le pourcentage de puissance CPU indiqué en paramètre.

Pour installer cet outil:
$ sudo apt-get install cpulimit

Lancer le processus et le limiter à 40% de CPU:
$ monprogramme & cpulimit -p $! -l 40

Les pourcentages indiqués ici correspondent aux pourcentages indiqués  par la commande top.

L'avantage de cette commande est que l'on peut attacher et détacher cpulimit d'un processus.

Pour l'utilisation d'un logiciel audio comme ardour3, vous pouvez l'attacher à cpulimit lorsque vous faîtes un traitement lourd (batch) sur de l'audio ou de la vidéo et le détacher lorsque vous mixez ou visionnez le résultat.

pour obtenir le PID d'un programme appelé monprogramme:
$ ps -axf | grep monprogramme

La première colonne donne le PID (un nombre entier).

Limiter un processus et ces processus fils sur Ubuntu 12.04


Enfin, la version de cpulimit sur Ubuntu 12.04 ne gère pas les processus childs. Cependant les dernières versions de cpulimit les gérent.

CPULimit peut être télécharger ici. Il vous faudra le compiler et l'installer.

$ tar xvfz cpulimit-2.2.tar.gz
$ cd cpulimit-2.2
$ make

Puis pour créer un package debian et l'installer:
$ sudo checkinstall -D make install

sinon pour installer directement:
$ sudo make install



Voilà, amusez-vous bien !
Musicalement,


Vous trouverez d'autres astuces pour l'audio et la musique sur Ubuntu par ici.