Linux Embedded

Le blog des technologies libres et embarquées

Découverte des mécanismes d’économie d’énergie du kernel Linux

Introduction

Dans le cadre de mon stage au sein de Smile ECS, j’ai travaillé sur des moyens d’optimiser la consommation énergétique des systèmes embarqués. Le but de ce post est de vous présenter une méthode pour mesurer la consommation et le fonctionnement des options d’optimisation proposées par le kernel Linux dans vos systèmes embarqués.

Nous allons également analyser les différences de consommation entre l’écriture sur un fichier chiffré et un fichier non chiffré.

Présentation de la carte iMX8M Mini Nitrogen

La carte iMX8M Mini Nitrogen est une carte embarquée conçue par NXP Semiconductors, présentée sur la Figure 1.

imx8 mini

Figure 1 : Carte iMX8M Mini

La carte est très performante et utilisée pour différents types d’applications multimédias (vidéo et audio), telles que les assistants vocaux, les systèmes de divertissement pour l’automobile ou encore la domotique. Le CPU de la carte possède quatre cœurs Cortex-A53 qui peuvent tourner à 3 fréquences : 1.2 GHz, 1.6 GHz, 1.8 GHz. Pour assurer le fonctionnement de la carte, il faut l’alimenter en 5V.

 

    Mesure de la consommation

    Présentation du Power Profiler Kit 2 (PPK2)

    Afin de mesurer la consommation électrique de l’iMX8M Mini, nous allons utiliser un outil de mesure développé par Nordic Semiconductor, le Power Profiler Kit 2 (Figure 2). Cet appareil permet de mesurer la consommation électrique d’appareils électroniques avec une précision pouvant aller jusqu’à 0.1 µA avec une intensité maximale de 1 A. L’appareil doit être alimenté en 5 V et 1 A. Il peut également être utilisé pour alimenter un système jusqu’à tension d'alimentation de 5V, notamment la carte iMX8M Mini.

    L’outil dispose d’un logiciel d’analyse qui mesure la consommation d’énergie en temps réel et affiche les résultats dans un graphique. Les données enregistrées (timestamp et courant) peuvent être exportées pour les analyser ultérieurement dans un format .csv. L’appareil peut mesurer pendant 500 secondes avec une fréquence d’échantillonnage de 100 kHz ou mesurer pendant 5000 secondes (83 minutes environ) avec une fréquence d’échantillonnage de 10 kHz.

    PPK2

    Figure 2 : Power Profiler Kit 2

    La connexion du PPK2 avec le PC se fait via USB. Une application liée au PPK2 permet d’observer la consommation du système et de l'analyser en temps réel.

    Graphique PPK2

    Figure 3: Graphique du PPK2

    A gauche, nous pouvons choisir la tension d’alimentation de la carte à alimenter ainsi que la fréquence d’échantillonnage et la durée de l’enregistrement du PPK2. En bas à gauche sont indiquées l’intensité moyenne sur toute la fenêtre, le pic d’intensité, la charge et le temps de la fenêtre. En grisé, nous observons les mêmes informations sur la partie sélectionnée.

    Pistes d’optimisations (effet des gouverneurs et optimisations proposées par le kernel)

    Effet des gouverneurs

    Le gouverneur définit les caractéristiques du CPU pour qu’il fonctionne dans un certain but. Il peut notamment être utilisé pour gérer la fréquence de fonctionnement des quatre cœurs de notre carte. Le kernel Linux possède plusieurs types de gouverneurs :

    • performance : Le CPU est réglé à sa fréquence la plus élevée statiquement pendant toute sa période de fonctionnement. Il est recommandé de l’utiliser pour exécuter des tâches longues et intensives afin de bénéficier d’une performance élevée.
    • powersave : Le CPU est réglé à sa fréquence la plus basse statiquement pendant toute sa période de fonctionnement. Il est recommandé de l’utiliser pour réduire la consommation électrique instantanée du CPU.
    • ondemand: Le CPU atteint une fréquence maximale lorsque la charge du CPU est importante et atteint une fréquence minimale lorsque la charge du CPU est faible. Ainsi la fréquence d’horloge est réglée dynamiquement de manière agressive.
    • conservative : Il a le même fonctionnement que le gouverneur ondemand, à la différence que la fréquence d’horloge est ajustée graduellement ce qui peut ajouter des latences au sein du système.

    Afin d’analyser les effets du gouverneur, nous avons créé un script qui vient modifier le gouverneur et qui lance un stress-ng sur les quatre CPUs avec le paramètre --cpu-ops de 10 000. Cela permet de simuler la même charge constante du CPU et donc de comparer les différents tests. Les commandes utilisées pour lancer 10 000 “calculs” sur les quatre CPUs ainsi que la consommation et le temps écoulé pour réaliser ces calculs sont présentés dans le tableau suivant:

    sleep 5

    stress-ng --cpu 4 --cpu-ops 10000

    sleep5

    courant mesuré(mA)

    temps (s)

    Energie consommée (J)

    idle 193    
    powersave 311 285 444.2
    conservative 450 203 456.8
    performance 452 204 461
    ondemand 454 203 460.8

    Lorsque le gouverneur est en powersave, le système consomme peu mais en contrepartie, il perd en performance étant donné qu’il a besoin de 80s de plus pour réaliser les différents calculs qu’en utilisant les autres gouverneurs. En effet, pour réaliser une tâche gourmande en processeur, le système doit privilégier le travail à haute fréquence, or en powersave il est fixé à la fréquence la plus basse. Il a donc besoin de plus de temps pour réaliser une tâche lourde.

    Concernant les gouverneurs conservative, performance et ondemand, les consommations et les temps d’exécution sont quasiment équivalents. Ils montrent tous les 3 une hausse de l'énergie consommée de 3.4% comparé au powersave. Cela s’explique par le fait que dans ces différents gouverneurs, la fréquence de fonctionnement de la carte s’adapte à la tâche à réaliser ; en l’occurrence, le système se met à la fréquence la plus haute lors du stress-ng.

    En somme, lorsque le gouverneur est en powersave le système est beaucoup moins énergivore en termes de courant mesuré mais perd en performance contrairement aux autres gouverneurs qui sont plus énergivores et plus rapides.

    Ainsi, le choix du gouverneur est primordial et lié aux besoins (performance ou économisation de l’énergie)

    Optimisations de consommation proposées par kernel

    Le kernel Linux propose quelques solutions pour optimiser la consommation énergétique de systèmes embarquant un Linux, notamment l'iMX8M Mini. Nous allons tester une des différentes solutions proposées pour vérifier leur impact en réalisant le même test que précédemment.

    Workqueue power efficiency : cette option détermine le comportement par défaut de la file d’attente de travail (workqueue) en termes d’efficacité énergétique. La file d’attente permet de planifier et exécuter les tâches en arrière-plan du noyau Linux.

    Afin de se rendre compte de l’utilité de cette optimisation, nous allons lancer un script qui utilise les workqueues et observer les différences.

    sleep 5

    stress-ng --cpu 4 --cpu-ops 10000

    sleep5

    workqueue power efficiency

    courant mesuré (mA) temps (s) Energie consommée (J)
    idle 193    
    powersave 317.4 284 450
    conservative 462.4 202 467
    performance 462 202 466.6
    ondemand 465 204 474.3

    L'état idle correspond au fonctionnement du système hors exécution du script de test.

    En comparant avec le tableau par défaut, nous observons globalement une légère hausse de l'énergie consommée de l’ordre de 1.9% en moyenne.

    Cette hausse de la consommation s’explique par le fait que nous utilisons une optimisation qui n’est pas pertinente dans ce test. En effet, l’efficacité des fonctions d’optimisation du kernel dépendent de la charge. Il est donc plus judicieux d’utiliser cette option pour des tâches qui font appel à des workqueues comme nous allons le voir par la suite au niveau de l’écriture sur les fichiers.

    Différence de consommation entre l’écriture sur un fichier chiffré et non-chiffré

    ftrace et trace-cmd

    ftrace est le framework générique du kernel Linux qui permet de suivre l’exécution du système en temps réel. L’outil fournit un moyen de suivre depuis l’espace utilisateur (userland) le comportement du noyau en enregistrant des points de passage dans le code et en les présentant dans le système de fichiers tracefs. Il permet de suivre les événements systèmes tels que les appels de fonctions, les interruptions et les changements de fréquence des CPUs. Pour ce faire, il utilise un buffer circulaire qui collecte les données en temps réel et écrase les données les plus anciennes lorsque le buffer est rempli. Ainsi, une analyse plus poussée peut être faite par rapport à ce qui s’est passé au niveau des appels systèmes et ainsi mieux comprendre la consommation.

    Cependant, l’analyse via tracefs peut être fastidieuse car elle nécessite d’écrire des paramètres dans plusieurs fichiers. Nous allons donc utiliser trace-cmd qui prend en charge la gestion des fichiers tracefs. Le programme permet de récupérer les résultats dans des fichiers bruts et, par souci de lisibilité, nous utilisons kernelshark, une interface graphique qui permet de visualiser les fichiers bruts générés.

    Dans notre cas, nous allons utiliser la connexion SSH pour enregistrer l’ensemble des données enregistrées réalisées par trace-cmd sur l’ordinateur. Cela permet de sauvegarder beaucoup plus de données car nous ne sommes alors plus limités par la capacité de stockage de l’iMX8M Mini et cela permet de diminuer l'impact de trace-cmd sur la consommation. En effet, trace-cmd peut s’avérer assez énergivore et peut perturber les mesures de consommation.

    Visualisation des évènements système

    stress-ng --hdd 1 --hdd-bytes 1M --hdd-opts sync --hdd-ops 1000 fichier chiffré fichier non-chiffré
    Moyenne du courant mesuré (mA) 280.55 293.21
    Temps (s) 9.08 6.37
    Energie consommée (J) 12.74 9.34

    La consommation est effectivement plus élevée pour l'écriture de données sur un fichier chiffré que sur un fichier non-chiffré (hausse de 30% de la consommation énergétique). Nous allons voir les différences au niveau des évènements systèmes qui impliquent cette différence de consommation.

    events non chiffré

    Figure 4: Visualisation avec ftrace des appels systèmes et des événements kernel lors de l’écriture de 64 ko sur un fichier non-chiffré

    L’écriture de données sur un fichier non-chiffré s’effectue de la manière suivante :

    l'événement sys_enter_lseek opère le changement de pointeur de la tête de lecture. Cela permet d’écrire des données à une position définie. Ensuite, l'événement sys_enter_write qui permet d’entamer le début de l’écriture avec un certain nombre d’octets. Par la suite, un ensemble de workqueues sont appelées via les kworker et softirq. Les workqueues sont des listes d’attente qui gèrent le lancement des tâches. Ainsi, lorsque les CPUs sont libres, les tâches qui étaient en attente sont lancées. En l'occurrence un kworker fait appel à jbd2/mmcblk1p2 qui se charge d'effectuer la mise à jour de la partition et permet l’écriture des octets. Pour ce faire, il utilise la fonction blk_mq_run_work_fn qui se charge d’effectuer l’écriture et la fonction mmc_blk_mq_complete_work indique la fin de l’écriture. A la fin, l’évènement sys_exit_write indique la sortie de l’appel système write et donc que l'écriture des octets a été réalisée.

    Le temps d’écriture d’un bloc de 64 ko prend environ 10 ms. Cette opération est répétée jusqu’à ce que l’ensemble des octets soit écrit.

    events chiffré

    Figure 5 : Visualisation avec ftrace des appels systèmes et des événements kernel de l’écriture de 64 ko sur un fichier chiffré

    Pour l’écriture sur un fichier chiffré, le principe est très similaire à celui de l’écriture sur un fichier non-chiffré mais une nouvelle tâche appararaît : dmcrypt_write. En effet, un kworker fait appel à jbd2/dm-0-8 (on écrit bien sur la partition chiffrée) qui appelle le workqueue kcryptd qui se charge de lancer la tâche dmcrypt_write. Cette tâche utilise les fonctions blk_mq_run_work_fn et mmc_blk_mq_complete_work qui ont les mêmes principes que ce que nous avons vu précédemment. Le temps d’écriture d’un bloc de 64 ko prend environ 13 ms.

    Avec trace-cmd analyse, nous pouvons observer les temps passés par les différentes tâches appelées. A partir de ces statistiques, nous pouvons dresser des histogrammes qui représentent le temps passé par les différents appels systèmes présentés sur la Figure 6.

    Tâches ecriture fichier

    Figure 6 : Statistiques des tâches pour l’écriture sur un fichier chiffré et non-chiffré

    Lors de l’écriture sur un fichier chiffré, les workqueues (kworker et kthread) sont plus importants engendrant un temps d’écriture plus long. De plus, la tâche dmcrypt_write, qui vient écrire sur le fichier chiffré, augmente également le temps d’écriture.

    En somme, l’écriture des données fait appel à plusieurs workqueues, il peut donc être pertinent d’utiliser l’option workqueue efficiency du kernel pour réduire la consommation.

    Intérêt du workqueue power efficiency

    Comme nous l'avons vu dans la partie précédente, il est judicieux d’utiliser le workqueue power efficiency car plusieurs workqueues sont appelées lors de l’écriture sur un fichier chiffré ou non-chiffré. Cette option est proposée dans le kernel Linux comme nous l’avons vu précédemment.

    Nous allons donc réaliser le même test que précédemment en activant le workqueue power efficiency.

    stress-ng --hdd 1 --hdd-bytes 1M --hdd-opts sync --hdd-ops 1000 

    workqueue_enabled

    fichier chiffré fichier non-chiffré
    Moyenne du courant mesuré (mA) 286 288.76
    Temps (s) 7.20 4.62
    Energie consommée sans workqueue power efficiency (J) 12.74 9.34
    Energie consommée avec workqueue power efficiency (J) 10.30 -> -19 % 6.67 -> -28%

     

    events non chiffré

    Figure 7 : Statistiques des évènements systèmes pour l’écriture sur un fichier non-chiffré avec et sans workqueue power efficiency

    events chiffré

    Figure 8 : Statistiques des évènements systèmes pour l’écriture sur un fichier chiffré avec et sans workqueue power efficiency

    Il y a une baisse significative de la consommation sur l’écriture d’un fichier chiffré (-19.17%) et sur l’écriture d’un fichier non-chiffré (-28.58%). En effet, la proportion de workqueue (kworker) a grandement diminué au niveau des appels systèmes. Il est donc pertinent d’utiliser les optimisations proposées par le kernel avec une charge adaptée afin de réduire la consommation d’un système Linux. 

    Conclusion

    En conclusion, nous avons vu qu’il y a des optimisations proposées par le kernel Linux qui permettent d’économiser la consommation énergétique. Ces optimisations ne sont pertinentes pour optimiser la consommation que si elles sont utilisées en fonction de la charge comme c’est le cas avec le workqueue power efficiency. ces observations ont pu être réalisées à l'aide du PPK2, un outil qui permet de mesurer la consommation énergétique des systèmes embarqués.

    Laisser un commentaire

    Votre adresse de messagerie ne sera pas publiée.