{"id":308,"date":"2011-03-11T16:00:05","date_gmt":"2011-03-11T15:00:05","guid":{"rendered":"http:\/\/www.blaess.fr\/christophe\/?p=308"},"modified":"2011-03-11T16:00:05","modified_gmt":"2011-03-11T15:00:05","slug":"temps-reel-et-economie-denergie-2","status":"publish","type":"post","link":"https:\/\/www.blaess.fr\/christophe\/2011\/03\/11\/temps-reel-et-economie-denergie-2\/","title":{"rendered":"Temps-r\u00e9el et \u00e9conomie d&rsquo;\u00e9nergie (2)"},"content":{"rendered":"<p>(Cet article est un extrait de la version pr\u00e9paratoire de mon livre \u00ab\u00a0<em>Applications temps-r\u00e9el avec Linux<\/em> \u00bb en cours d\u2019\u00e9criture)<\/p>\n<p>&nbsp;<\/p>\n<h1>\u00c9conomie ou performance&nbsp;: arbitrage pour le temps-r\u00e9el embarqu\u00e9 (Partie 2)<\/h1>\n<p>Nous avons examin\u00e9 dans le <a title=\"Temps-r\u00e9el et \u00e9conomie d\u2019\u00e9nergie (1)\" href=\"http:\/\/www.blaess.fr\/christophe\/2011\/03\/05\/temps-reel-et-economie-d-energie-1\/\">pr\u00e9c\u00e9dent billet<\/a> le fonctionnement des <em>governors<\/em>, les modules qui permettent au noyau Linux de r\u00e9gler la fr\u00e9quence du processeur, en tenant compte de certaines heuristiques (privil\u00e9gier les \u00e9conomies d&rsquo;\u00e9nergie, la performance du calcul, ou s&rsquo;adapter automatiquement).<br \/>\n<!--more-->\n<br \/>\nPour un syst\u00e8me embarqu\u00e9, il est habituellement important d&rsquo;\u00e9conomiser l&rsquo;\u00e9nergie \u00e9lectrique, que ce soit pour pr\u00e9server la batterie ou pour \u00e9viter d&rsquo;incorporer un syst\u00e8me de refroidissement encombrant. Durant certaines phases de fonctionnement (attente de commande utilisateur, entr\u00e9es-sorties sur des fichiers, communication r\u00e9seau, etc.) la r\u00e9activit\u00e9 et la vitesse de traitement du processeur importent peu, et il est possible d&rsquo;envisager de ralentir le CPU. \u00c0 d&rsquo;autres moments (attente d&rsquo;interruption, phase de calcul urgente&#8230;) on pr\u00e9f\u00e9rera pousser le processeur au maximum de sa puissance de traitement.<\/p>\n<p>Pourquoi utiliser un <em>governor<\/em> (\u00ab\u00a0powersave\u00a0\u00bb ou \u00ab\u00a0performance\u00a0\u00bb par exemple) plut\u00f4t que de fixer directement soi-m\u00eame les fr\u00e9quences de fonctionnement (en remplissant\u00a0<code>\/sys\/devices\/system\/cpu\/<\/code>num\u00e9ro de cpu<code>\/cpufreq\/scaling_cur_freq<\/code>)&nbsp;? Tout simplement pour am\u00e9liorer la portabilit\u00e9 de notre code, qui pourra ainsi \u00e9voluer sur de nouveaux processeurs sans \u00eatre d\u00e9pendant des fr\u00e9quences absolues support\u00e9es par tel ou tel CPU.<\/p>\n<p>Nous devons auparavant v\u00e9rifier la r\u00e9activit\u00e9 du syst\u00e8me lors d&rsquo;une demande de basculement entre un <em>governor<\/em> (par exemple \u00ab\u00a0powersave\u00a0\u00bb) et un autre (disons \u00ab\u00a0performance\u00a0\u00bb). Pour cela, on peut utiliser le programme <code>test-changement-governor.c<\/code>, qui se trouve dans l&rsquo;archive suivante&nbsp;: <a href=\"http:\/\/www.blaess.fr\/christophe\/files\/test-governors-2.tar.bz2\">http:\/\/www.blaess.fr\/christophe\/files\/test-governors-2.tar.bz2<\/a>. Il permet de lancer deux threads&nbsp;: le premier active,\u00a0sur le processeur o\u00f9 l&rsquo;autre thread s&rsquo;ex\u00e9cute, un\u00a0<em>governor<\/em> indiqu\u00e9 en argument sur la ligne de commande. Le second d\u00e9marre une s\u00e9rie de boucles actives au bout d&rsquo;une seconde. Arriv\u00e9 \u00e0 la moiti\u00e9 de sa s\u00e9rie, il notifie le premier thread qui bascule alors sur un second <em>governor<\/em> (indiqu\u00e9 \u00e9galement sur la ligne de commande). Nous pourrons ainsi observer le temps de transition.<\/p>\n<p>Voici un exemple d&rsquo;ex\u00e9cution (\u00e0 faire fonctionner avec les droits\u00a0<em>root<\/em>)&nbsp;:<\/p>\n<pre># <strong>.\/test-changement-governor<\/strong>\nusage: .\/test-changement-governor governor_1 governor_2\n# <strong>.\/test-changement-governor powersave performance<\/strong>\n   0   1788\n   1   1778\n   2   1789\n [...]\n  48   1770\n  49   1795\n  50    914\n  51    761\n [...]\n  97    760\n  98    754\n  99    760\n#<\/pre>\n<p>Ce que l&rsquo;on peut repr\u00e9senter par le graphique suivant (en abcisse les boucles actives, en ordonn\u00e9es les dur\u00e9es)&nbsp;:<\/p>\n<p><a href=\"http:\/\/www.blaess.fr\/christophe\/wp-content\/uploads\/2011\/03\/test-changement.gif\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-324\" title=\"test-changement\" src=\"http:\/\/www.blaess.fr\/christophe\/wp-content\/uploads\/2011\/03\/test-changement.gif\" alt=\"\" width=\"640\" height=\"480\" \/><\/a>Le temps de basculement est plut\u00f4t rapide, d\u00e8s que le premier thread a \u00e9crit le nom du <em>governor<\/em> dans le fichier\u00a0<code>\/sys\/devices\/system\/cpu\/<\/code>&lt;numero de cpu&gt;<code>\/cpufreq\/scaling_governor<\/code>, la fr\u00e9quence du cpu augmente imm\u00e9diatement ce qui r\u00e9duit le temps d&rsquo;ex\u00e9cution d&rsquo;une boucle active.<\/p>\n<p>On peut donc tr\u00e8s bien imaginer, dans une application temps-r\u00e9el d&rsquo;augmenter la fr\u00e9quence CPU avant d&rsquo;entrer dans une portion de code relativement critique en terme de temps d&rsquo;ex\u00e9cution avec un&nbsp;:<\/p>\n<pre>fd = open(\"\/sys\/devices\/system\/cpu\/cpu0\/cpufreq\/scaling_governor, O_WRONLY);\nif (fd &lt; 0) {\n  perror(\"cpufreq\");\n  exit(1);\n}\nwrite(fd, \"performance\", 11);  \/* 11 = strlen(\"performance\") *\/<\/pre>\n<p>Puis, une fois le besoin en puissance CPU amoindri&nbsp;:<\/p>\n<pre> write(fd, \"powersave\", 9); \/* 9 = strlen(\"powersave\") *\/<\/pre>\n<p>NB&nbsp;: il faut penser \u00e0 adapter le num\u00e9ro de processeur dans le chemin fourni \u00e0 <code>open()<\/code>.<\/p>\n<p>Avant d&#8217;employer r\u00e9ellement cette technique dans une application temps-r\u00e9el, il est n\u00e9cessaire de mesure le temps pris par la modification du <em>governor<\/em>. Pour cela nous pouvons utiliser le programme <code>mesure-changement-governor.c<\/code>, pr\u00e9sent dans l&rsquo;archive mentionn\u00e9e plus haut.<\/p>\n<pre># <strong>.\/mesure-changement-governor powersave performance<\/strong>\nDuree de modification : 51us\n#<\/pre>\n<p>Sur cette plateforme (Intel dual-core 2&#215;1.86 GHz), le temps n\u00e9cessaire pour modifier le <em>governor<\/em> est d&rsquo;une cinquantaine de micro-secondes. Si les contraintes temporelles sont de l&rsquo;ordre de la milliseconde, nous pouvons tout \u00e0 fait int\u00e9grer cette variation dynamique, contr\u00f4l\u00e9e par notre application. Il est important de v\u00e9rifier cette dur\u00e9e (et l&rsquo;ensemble des autres \u00e9l\u00e9ments que nous avons mesur\u00e9 dans ces deux articles) sur la plateforme cible, pour s&rsquo;assurer que l&rsquo;\u00e9conomie d&rsquo;\u00e9nergie obtenue en ex\u00e9cutant les t\u00e2ches de moindre importance \u00e0 faible vitesse est conciliable avec la r\u00e9activit\u00e9 rapide n\u00e9cessaire pour les parties critiques du syst\u00e8me temps-r\u00e9el.<\/p>\n<p>&nbsp;<\/p>","protected":false},"excerpt":{"rendered":"<p>(Cet article est un extrait de la version pr&eacute;paratoire de mon livre &laquo;&nbsp;Applications temps-r&eacute;el avec Linux&nbsp;&raquo; en cours d&rsquo;&eacute;criture) &nbsp; &Eacute;conomie ou performance&nbsp;: arbitrage pour le temps-r&eacute;el embarqu&eacute; (Partie 2) Nous avons examin&eacute; dans le pr&eacute;c&eacute;dent billet le fonctionnement des governors, les modules qui permettent au noyau Linux de r&eacute;gler la fr&eacute;quence du processeur, [&hellip;]<\/p>","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[5,8,14],"tags":[],"class_list":["post-308","post","type-post","status-publish","format-standard","hentry","category-embarque","category-linux-2","category-temps-reel"],"_links":{"self":[{"href":"https:\/\/www.blaess.fr\/christophe\/wp-json\/wp\/v2\/posts\/308","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.blaess.fr\/christophe\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.blaess.fr\/christophe\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.blaess.fr\/christophe\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.blaess.fr\/christophe\/wp-json\/wp\/v2\/comments?post=308"}],"version-history":[{"count":0,"href":"https:\/\/www.blaess.fr\/christophe\/wp-json\/wp\/v2\/posts\/308\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.blaess.fr\/christophe\/wp-json\/wp\/v2\/media?parent=308"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.blaess.fr\/christophe\/wp-json\/wp\/v2\/categories?post=308"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.blaess.fr\/christophe\/wp-json\/wp\/v2\/tags?post=308"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}