Lamourec Alain a écrit :
> 
> Je confirme pour les processeurs intel.
> Ce matin, sur un dépannage, pas de rotation du ventilateur du processeur :
> - l'interface graphique de moins en fluide
> - plein de processus idle_inject
> - le PC s'arrête pour une température de 100°

        Je pose donc ceci ici :

hilbert:[~/cpufreqd] > cat cpufreqd.conf
#define         FILE_TEMP       "/sys/class/thermal/thermal_zone0/temp"
#define         FILE_HZ         "/sys/devices/system/cpu"

#define         MAX_TEMP        65
#define         POLL_HZ         2
#define         COEFF           0.8

hilbert:[~/cpufreqd] > cat cpufreqd.rpl | expand -t4
#!/usr/local/bin/rpl -sp

#include "cpufreqd.conf"

CPUFREQD
<<
    daemonize

    nbrcpus
    dup 1 ->list crtab
    -> NCPU TCPU
    <<
        1 NCPU for I
            FILE_HZ "/cpu" + I decr ->str + "/cpufreq/" +
            -> R
            <<
                "NAME" R "cpuinfo_min_freq" + 2 ->list 1 ->list
                { "OLD" "FLOW" "SEQUENTIAL" "READONLY" } +
                open
                { "LINE*(*)" } swap format
                dup read 1 get str-> swap close

                "NAME" R "cpuinfo_max_freq" + 2 ->list 1 ->list
                { "OLD" "FLOW" "SEQUENTIAL" "READONLY" } +
                open
                { "LINE*(*)" } swap format
                dup read 1 get str-> swap close

                dup 3 ->list 'TCPU' swap I 1 ->list swap put
            >>
        next

        do
            { { "NAME" FILE_TEMP } "OLD" "FLOW"
                    "SEQUENTIAL" "READONLY" }
            open
            { "LINE*(*)" } swap format
            -> FICHIER
            <<
                FICHIER read
                1 get str-> 1000 /

                FICHIER close
            >>

            -> TEMP
            <<
                if
                    TEMP MAX_TEMP >=
                then
                    COEFF
                else
                    COEFF inv
                end

                TCPU
                UPDATE_FREQUENCIES
                'TCPU' sto

                TCPU
                WRITE_FREQUENCIES
            >>

            POLL_HZ inv wait
        until
            false
        end
    >>
>>

WRITE_FREQUENCIES
<<
    -> TCPU
    <<
        1 NBRCPUS for I
            "NAME" FILE_HZ "/cpu" + I decr ->str +
            "/cpufreq/scaling_max_freq" + 2 ->list 1 ->list
            { "REPLACE" "FLOW" "SEQUENTIAL" } + open
            { "LENGTH*(*)" } swap format
            -> FICHIER
            <<
                TCPU I 1 ->list get 3 get ->str 1 ->list
                FICHIER write
                FICHIER close
            >>
        next
    >>
>>


UPDATE_FREQUENCIES
<<
    -> C TCPU
    <<
        1 NBRCPUS for I
            TCPU I 1 ->list get list-> drop dup C *
            -> FMIN FMAX FCUR NFCUR
            <<
                if
                    C 1 <
                then
                    if
                        NFCUR FMIN <
                    then
                        FMIN
                    else
                        NFCUR
                    end

                else
                    if
                        NFCUR FMAX >
                    then
                        FMAX
                    else
                        NFCUR
                    end
                end

                ip

                FMIN FMAX rot 3 ->list
            >>

            'TCPU' swap I 1 ->list swap put
        next

        TCPU
    >>
>>
hilbert:[~/cpufreqd] >

        C'est du quick and dirty codé en une petite heure, mais ça fait le
boulot et je ne pense pas qu'il y ait besoin d'un PID sophistiqué. Avec
ça, le CPU ne dépasse pas les 70°C en pic et 65 à 68°C en moyenne, même
en recompilant un gros soft avec make -j12.

        On ne peut le faire qu'en polling. Les interfaces de /sys ne sont mises
à jour que lors d'une opération de lecture (et certaines dont la
température ne le sont que lors de l'ouverture du fichier correspondant,
si le fichier n'est pas ouvert à chaque lecture, la température n'est
pas remise à jour). Il est donc impossible d'utiliser un mécanisme comme
inotify.

        Le daemon lit la température deux fois par seconde et ajuste la vitesse
de tous les coeurs en fonction. Il ne touche pas au drapeau boost.

        À utiliser avec la version de développement du RPL/2
(https://rpl2.systella.fr) sous peine de se prendre un coup de pied au
fesses lors de la lecture de la température (rpl-4.1.37-daily ou suivantes).

        Lors du lancement, le truc se transforme en daemon et est récupéré par
init, tout en affichant sur la sortie standard son PID réel. Un simple
SIGTERM l'arrête proprement (mais la fréquence maximale du CPU reste
dans l'état courant). Il faudrait que je rajoute une procédure ATEXIT.
Le langage permet d'ajouter la fonction en deux ou trois minutes. Si ça
intéresse quelqu'un, je peux le faire, faites-le moi savoir. Je peux
même empaqueter le tout dans un .deb.

        J'ai aussi découvert un truc étrange : il faut lire une ligne (terminée
par "\n" d'où le format "line*(*)") pour les températures, mais
uniquement écrire un nombre formaté (sans le "\n" d'où le "length*(*)")
pour spécifier la fréquence maximale... Pas très cohérent, mais ça
fonctionne.

        JB

Attachment: signature.asc
Description: OpenPGP digital signature

Répondre à