{"id":414,"date":"2011-04-01T15:11:43","date_gmt":"2011-04-01T14:11:43","guid":{"rendered":"http:\/\/www.blaess.fr\/christophe\/?p=414"},"modified":"2011-04-01T15:11:43","modified_gmt":"2011-04-01T14:11:43","slug":"groupement-automatique-des-processus","status":"publish","type":"post","link":"https:\/\/www.blaess.fr\/christophe\/2011\/04\/01\/groupement-automatique-des-processus\/","title":{"rendered":"[ACTU] Groupement automatique des processus"},"content":{"rendered":"<p style=\"text-align: justify;\">Depuis 2003, plusieurs ordonnanceurs se sont succ\u00e9d\u00e9 dans le noyau Linux 2.6. Le dernier en date (apparu dans Linux 2.6.24) est le <em>\u00ab\u00a0CFS &#8211; Complete Fair Scheduler\u00a0\u00bb<\/em> autrement dit \u00ab\u00a0l&rsquo;ordonnanceur vraiment \u00e9quitable\u00a0\u00bb. Celui-ci\u00a0garantit que le temps CPU disponible est r\u00e9parti de mani\u00e8re \u00e9quitable entre les diff\u00e9rentes t\u00e2ches. Ceci ne concerne naturellement que les t\u00e2ches ordonnanc\u00e9es en temps-partag\u00e9, celles s&rsquo;ex\u00e9cutant en temps-r\u00e9el disposent de tout le temps-processeur qu&rsquo;elles d\u00e9sirent (voir toutefois <a title=\"Partager le temps-r\u00e9el&nbsp;?\" href=\"http:\/\/www.blaess.fr\/christophe\/2011\/03\/25\/partager-le-temps-reel\/\">cet article&#8230;<\/a>)<\/p>\n<p>\n<!--more-->\n<\/p>\n<p style=\"text-align: justify;\">Pour am\u00e9liorer le temps de r\u00e9ponse des applications interactives (notamment l&rsquo;interface utilisateur graphique), ce <em>scheduler<\/em> propose un partage du temps CPU entre les groupes de processus.\u00a0Supposons que nous ayons un premier groupe de dix t\u00e2ches r\u00e9alisant des calculs intensifs (la compilation d&rsquo;un projet important comme le noyau Linux). Le temps processeur sera alors r\u00e9parti en dix tranches de 10&nbsp;% (en ignorant les quelques pourcents indispensables pour faire fonctionner les autres processus du syst\u00e8me). Si nous ajoutons \u00e0 pr\u00e9sent un second groupe de trois processus de calcul, la r\u00e9partition se fera ainsi\u00a0:<\/p>\n<ul>\n<li>5&nbsp;% pour chacun des trois processus du premier groupe qui totalise donc 50%\u00a0;<\/li>\n<li>16,6&nbsp;% pour chacun des trois processus du second groupe, qui re\u00e7oit les 50% restants.<\/li>\n<\/ul>\n<p style=\"text-align: justify;\">&nbsp;<\/p>\n<p style=\"text-align: justify;\">Ce m\u00e9canisme, tr\u00e8s pratique, est malheureusement assez compliqu\u00e9 \u00e0 mettre en \u0153uvre, et doit \u00eatre explicitement activ\u00e9 lors de la cr\u00e9ation des t\u00e2ches \u00e0 placer dans les groupes.<\/p>\n<p style=\"text-align: justify;\">Dans le noyau 2.6.38 &#8211; publi\u00e9 r\u00e9cemment comme je l&rsquo;avais signal\u00e9 dans un <a title=\"Linux 2.6.38\" href=\"http:\/\/www.blaess.fr\/christophe\/2011\/03\/16\/linux-2-6-38\/\">pr\u00e9c\u00e9dent article<\/a> &#8211; est apparu un nouvel \u00e9l\u00e9ment de configuration nomm\u00e9 <code>CONFIG_SCHED_AUTOGROUP<\/code>. Celui-ci est accessible dans le menu \u00ab\u00a0<em>General Setup\u00a0\u00bb<\/em> de l&rsquo;interface de configuration du kernel (<code>make menuconfig<\/code>, <code>make xconfig<\/code>, ou <code>make gconfig<\/code>) sous la d\u00e9nomination \u00ab\u00a0<em>Automatic process group scheduling\u00a0\u00bb<\/em> .<\/p>\n<p style=\"text-align: justify;\">Avec l&rsquo;auto-groupement des t\u00e2ches, l&rsquo;ordonnanceur prend automatiquement en consid\u00e9ration le terminal de contr\u00f4le du processus. Le temps CPU est r\u00e9parti \u00e9quitablement entre les terminaux, quelque soit le nombre de t\u00e2ches sur chaque terminal.<\/p>\n<p style=\"text-align: justify;\">Pour tester cette fonctionnalit\u00e9, nous allons utiliser le <a title=\"boucles-actives.c\" href=\"http:\/\/www.blaess.fr\/christophe\/files\/article-2011-04-01\/boucles-actives.c\" target=\"_blank\">petit programme suivant<\/a>, qui lance en parall\u00e8le le nombre de processus demand\u00e9 sur sa ligne de commande. Chaque processus consomme, dans une boucle active, tout le temps CPU qui lui est offert\u00a0:<\/p>\n<pre><strong>boucles-actives.c\u00a0:<\/strong>\n#include &lt;stdio.h&gt;\n#include &lt;stdlib.h&gt;\n#include &lt;unistd.h&gt;\n\nint main(int argc, char * argv[])\n{\n\tint nb;\n\tif ((argc != 2) || (sscanf(argv[1], \"%d\", &amp; nb) != 1)) {\n\t\tfprintf(stderr, \"usage: %s n\", argv[0]);\n\t\texit(1);\n\t}\n\twhile (nb &gt; 0) {\n\t\tif (fork() == 0)\n\t\t\twhile (1)\n\t\t\t\t;\n\t\tnb --;\n\t}\n\treturn 0;\n}<\/pre>\n<p>Ouvrons un terminal et lan\u00e7ons un premier jeu de processus. Nous observons que la charge CPU monte en fl\u00e8che.<br \/>\n<a href=\"http:\/\/www.blaess.fr\/christophe\/wp-content\/uploads\/2011\/03\/terminal-1.gif\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-430\" title=\"Terminal-1\" src=\"http:\/\/www.blaess.fr\/christophe\/wp-content\/uploads\/2011\/03\/terminal-1.gif\" alt=\"Linux Sched Autogroup 1\" width=\"620\" height=\"379\" \/><\/a><\/p>\n<p style=\"text-align: justify;\">Basculons alors sur un autre bureau virtuel et ouvrons un second terminal. Premi\u00e8re surprise&nbsp;: la fluidit\u00e9 de l&rsquo;interface graphique. Les applications de l&rsquo;environnement graphique (Gnome sur ce poste) n&rsquo;ont pas de terminaux de contr\u00f4le et appartiennent donc \u00e0 un groupe diff\u00e9rent de celui des processus en boucle. Le temps processeur dont elles ont besoin est donc r\u00e9serv\u00e9 et nous n&rsquo;observons plus de saccades dans la gestion de la souris par exemple comme ce pouvait \u00eatre le cas pr\u00e9c\u00e9dement.\u00a0Ce point a d&rsquo;ailleurs \u00e9t\u00e9 longuement comment\u00e9 suite \u00e0 un <a title=\"sched: automated per tty task groups\" href=\"http:\/\/lkml.org\/lkml\/2010\/11\/14\/222\" target=\"_blank\">message enthousiaste<\/a> de Linus Torvalds en novembre dernier lorsqu&rsquo;il s&rsquo;est aper\u00e7u que son interface graphique conservait toute sa r\u00e9activit\u00e9, m\u00eame durant une compilation largement parall\u00e9lis\u00e9e du noyau.<\/p>\n<p>Ouvrons un second terminal et lan\u00e7ons une deuxi\u00e8me s\u00e9rie de processus en boucle&nbsp;:<\/p>\n<p><a href=\"http:\/\/www.blaess.fr\/christophe\/wp-content\/uploads\/2011\/03\/terminal-2.gif\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-431\" title=\"Terminal 2\" src=\"http:\/\/www.blaess.fr\/christophe\/wp-content\/uploads\/2011\/03\/terminal-2.gif\" alt=\"Linux Sched Autogroup 2\" width=\"647\" height=\"389\" \/><\/a><\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p style=\"text-align: justify;\">Puis en basculant sur un troisi\u00e8me terminal, observons les r\u00e9partitions de temps processeur (sur cette machine, le processeur dispose de deux c\u0153urs, aussi la somme des temps CPU est de 200%)\u00a0:<\/p>\n<pre>$ <strong>ps axu<\/strong>\nUSER     PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND\nroot       1  0.0  0.0   2876  1332 ?        Ss   Mar29   0:01 \/sbin\/init\nroot       2  0.0  0.0      0     0 ?        S    Mar29   0:00 [kthreadd]\n[...]\ncpb     7413 10.1  0.0   1864    48 pts\/0    R    08:24   0:07 .\/boucles-actives 10\ncpb     7414 10.3  0.0   1864    48 pts\/0    R    08:24   0:07 .\/boucles-actives 10\ncpb     7415 10.0  0.0   1864    48 pts\/0    R    08:24   0:07 .\/boucles-actives 10\ncpb     7416 10.3  0.0   1864    48 pts\/0    R    08:24   0:07 .\/boucles-actives 10\ncpb     7417 10.3  0.0   1864    48 pts\/0    R    08:24   0:07 .\/boucles-actives 10\ncpb     7418 10.3  0.0   1864    48 pts\/0    R    08:24   0:07 .\/boucles-actives 10\ncpb     7419 10.3  0.0   1864    48 pts\/0    R    08:24   0:07 .\/boucles-actives 10\ncpb     7420 10.1  0.0   1864    48 pts\/0    R    08:24   0:07 .\/boucles-actives 10\ncpb     7421 10.1  0.0   1864    48 pts\/0    R    08:24   0:07 .\/boucles-actives 10\ncpb     7422 10.1  0.0   1864    48 pts\/0    R    08:24   0:07 .\/boucles-actives 10\ncpb     7425 23.4  0.0   1864    48 pts\/1    R    08:24   0:15 .\/boucles-actives 4\ncpb     7426 24.0  0.0   1864    48 pts\/1    R    08:24   0:16 .\/boucles-actives 4\ncpb     7427 23.7  0.0   1864    48 pts\/1    R    08:24   0:16 .\/boucles-actives 4\ncpb     7428 23.4  0.0   1864    48 pts\/1    R    08:24   0:15 .\/boucles-actives 4\ncpb     7456  0.0  0.0   4764   988 pts\/2    R+   08:25   0:00 ps axu\n$<\/pre>\n<p style=\"text-align: justify;\">Nous voyons bien que les dix processus issus de la commande &lsquo;<code>boucles-actives 10<\/code>\u00a0\u00bb disposent chacun de 10\u00a0% du temps CPU, tandis que ceux lanc\u00e9s par la commande \u00ab\u00a0<code>boucles-actives 4<\/code>\u00a0\u00bb profitent d&rsquo;environ 25\u00a0% chacun. Pour voir les groupes de processus, nous pouvons utiliser la commande suivante\u00a0:<\/p>\n<pre>$ <strong>ps ax -O pgrp<\/strong>\n  PID  PGRP S TTY          TIME COMMAND\n    1     1 S ?        00:00:01 \/sbin\/init\n    2     0 S ?        00:00:00 [kthreadd]\n[...]\n 7413  7412 R pts\/0    00:00:15 .\/boucles-actives 10\n 7414  7412 R pts\/0    00:00:14 .\/boucles-actives 10\n 7415  7412 R pts\/0    00:00:14 .\/boucles-actives 10\n 7416  7412 R pts\/0    00:00:14 .\/boucles-actives 10\n 7417  7412 R pts\/0    00:00:14 .\/boucles-actives 10\n 7418  7412 R pts\/0    00:00:14 .\/boucles-actives 10\n 7419  7412 R pts\/0    00:00:14 .\/boucles-actives 10\n 7420  7412 R pts\/0    00:00:14 .\/boucles-actives 10\n 7421  7412 R pts\/0    00:00:14 .\/boucles-actives 10\n 7422  7412 R pts\/0    00:00:14 .\/boucles-actives 10\n 7425  7424 R pts\/1    00:00:32 .\/boucles-actives 4\n 7426  7424 R pts\/1    00:00:34 .\/boucles-actives 4\n 7427  7424 R pts\/1    00:00:33 .\/boucles-actives 4\n 7428  7424 R pts\/1    00:00:34 .\/boucles-actives 4\n 7477  7477 R pts\/2    00:00:00 ps ax -O pgrp\n$<\/pre>\n<p style=\"text-align: justify;\">Le num\u00e9ro de groupe est indiqu\u00e9 en seconde colonne, le groupe 7412 contient les dix processus ayant chacun 10\u00a0% du temps CPU et le groupe 7424 est constitu\u00e9 des quatre processus avec 25\u00a0% de temps CPU chacun. La nouveaut\u00e9 du noyau 2.6.38 est d&rsquo;organiser automatiquement ces groupes en se basant sur le terminal de contr\u00f4le (<code>pts\/0<\/code> dans un cas et <code>pts\/1<\/code> dans l&rsquo;autre).<\/p>\n<p style=\"text-align: justify;\">En conclusion, je ne peux que saluer cette nouveaut\u00e9 du noyau 2.6.38. Elle est particuli\u00e8rement utile pour conserver une bonne r\u00e9activit\u00e9 \u00e0 un syst\u00e8me sur lequel de nombreuses t\u00e2ches de calcul s&rsquo;ex\u00e9cutent. L&#8217;emploi du terminal de contr\u00f4le des processus limite toutefois la port\u00e9e de cette innovation, car la plupart des utilisateurs de Linux ex\u00e9cutent des applications purement graphiques (navigateurs, <em>players<\/em> vid\u00e9o, etc.) dans des environnements (Gnome, Kde, Xfce&#8230;) o\u00f9 la notion de terminal est absente. Ces processus sont pr\u00e9sent\u00e9s avec un point d&rsquo;interrogation dans la colonne <code>TTY<\/code> de <code>ps<\/code>. Les principaux b\u00e9n\u00e9ficiaires seront plut\u00f4t les utilisateurs qui lancent r\u00e9guli\u00e8rement des t\u00e2ches consommatrices de CPU (compilation, traitement vid\u00e9o, calculs&#8230;) depuis des terminaux shell.<\/p>","protected":false},"excerpt":{"rendered":"<p>Depuis 2003, plusieurs ordonnanceurs se sont succ&eacute;d&eacute; dans le noyau Linux 2.6. Le dernier en date (apparu dans Linux 2.6.24) est le &laquo;&nbsp;CFS &ndash; Complete Fair Scheduler&nbsp;&raquo; autrement dit &laquo;&nbsp;l&rsquo;ordonnanceur vraiment &eacute;quitable&nbsp;&raquo;. Celui-ci&nbsp;garantit que le temps CPU disponible est r&eacute;parti de mani&egrave;re &eacute;quitable entre les diff&eacute;rentes t&acirc;ches. Ceci ne concerne naturellement que les t&acirc;ches ordonnanc&eacute;es [&hellip;]<\/p>","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[3,8,14],"tags":[],"class_list":["post-414","post","type-post","status-publish","format-standard","hentry","category-actualite","category-linux-2","category-temps-reel"],"_links":{"self":[{"href":"https:\/\/www.blaess.fr\/christophe\/wp-json\/wp\/v2\/posts\/414","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=414"}],"version-history":[{"count":0,"href":"https:\/\/www.blaess.fr\/christophe\/wp-json\/wp\/v2\/posts\/414\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.blaess.fr\/christophe\/wp-json\/wp\/v2\/media?parent=414"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.blaess.fr\/christophe\/wp-json\/wp\/v2\/categories?post=414"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.blaess.fr\/christophe\/wp-json\/wp\/v2\/tags?post=414"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}