{"id":2483,"date":"2016-09-19T14:50:06","date_gmt":"2016-09-19T18:50:06","guid":{"rendered":"http:\/\/bioinfo.iric.ca\/fr\/?p=2483"},"modified":"2017-04-29T17:04:48","modified_gmt":"2017-04-29T21:04:48","slug":"traitement-parallele-facile-avec-r-suite","status":"publish","type":"post","link":"https:\/\/bioinfo.iric.ca\/fr\/traitement-parallele-facile-avec-r-suite\/","title":{"rendered":"Traitement parall\u00e8le facile avec R (suite)"},"content":{"rendered":"<p>La derni\u00e8re fois que j&rsquo;ai abord\u00e9 ce sujet, je vous ai pr\u00e9sent\u00e9 une technique vraiment simple pour <a href=\"https:\/\/bioinfo.iric.ca\/fr\/traitement-parallele-facile-avec-r\/\">changer vos appels <code>lapply<\/code> en leur \u00e9quivalents parall\u00e8les <code>mclapply<\/code><\/a>. Mais bien que ce soit une modification extr\u00eamement simple \u00e0 impl\u00e9menter et qui donne d&rsquo;excellent gains en performance, celle-ci n\u00e9cessitait toutefois que votre code fasse d\u00e9j\u00e0 usage de lapply. Alors explorons une autre techinque simple pour introduire du traitement parall\u00e8le dans votre code source existant \u00e0 l&rsquo;aide des librairies <a href=\"https:\/\/cran.r-project.org\/web\/packages\/foreach\/index.html\">foreach<\/a> et <a href=\"https:\/\/cran.r-project.org\/web\/packages\/doMC\/index.html\">doMC<\/a>.<\/p>\n<p>La librairie foreach est ici essentielle parce qu&rsquo;elle impl\u00e9mente un type de boucle qui fait abstraction de toute forme de compteur, la rendant ainsi utilisable dans un contexte d&rsquo;\u00e9xecution en parall\u00e8le. Et, histoire de faire plaisir \u00e0 tous les fans du langage Python, foreach vous donnera quelque peu l&rsquo;impression de travailler avec les <em>list comprehensions<\/em> \ud83d\ude42<\/p>\n<p>Explorons donc un bout de code utilisant la librairie RandomForest puisqu&rsquo;elle nous permettra de toucher certains aspects cl\u00e9s de la boucle foreach.<\/p>\n<p>Tel qu&rsquo;observ\u00e9 dans le <a href=\"https:\/\/cran.r-project.org\/web\/packages\/randomForest\/randomForest.pdf\">manuel de r\u00e9f\u00e9rence de randomForest<\/a> \u00e0 propos du param\u00e8tre <code>ntree<\/code>:<\/p>\n<blockquote><p>ntree: Nombre d&rsquo;arbres \u00e0 faire cro\u00eetre.<br \/>\nCe nombre ne devrait pas \u00eatre trop petit afin d&rsquo;assurer que chaque<br \/>\nligne d&rsquo;entr\u00e9e sera pr\u00e9dite au moins quelques fois<\/p><\/blockquote>\n<p>Bien entendu, attribuer une valeur importante \u00e0 ntree r\u00e9sultera irr\u00e9m\u00e9diablement en un temps de traitement plus long&#8230; Mais avec l&rsquo;aide de foreach et doMC, nous serons en mesure de r\u00e9partir ce traitement sur plusieurs CPUs.<\/p>\n<p><strong>Ce bout de code:<\/strong><\/p>\n<pre><code class=\"r\">library(\"randomForest\")\r\n\r\n... # g\u00e9n\u00e9ration de votre ensemble d'entrainement\r\n\r\nrf <- randomForest(x=x, y=y, <strong>ntree=1000<\/strong>)\r\n<\/code><\/pre>\n<p><strong>Devient:<\/strong><\/p>\n<pre><code class=\"r\">library(\"randomForest\")\r\nlibrary(foreach)\r\nlibrary(doMC)\r\nregisterDoMC(4)\r\n\r\n... # g\u00e9n\u00e9ration des votre ensemble d'entrainement\r\n\r\nrf <-  foreach(ntree=rep(250, 4), <strong>.combine<\/strong>=combine, <strong>.packages<\/strong>='randomForest') %dopar% {<br \/>\r\n&nbsp;&nbsp;&nbsp;&nbsp;randomForest(x=x, y=y, <strong>ntree=ntree<\/strong>)<br \/>\r\n}\r\n<\/code><\/pre>\n<p>Voici les diff\u00e9rences cl\u00e9s \u00e0 observer dans le seconde version:<\/p>\n<ul>\n<li>Nous initialisons les librairies <a href=\"https:\/\/cran.r-project.org\/web\/packages\/foreach\/index.html\">foreach<\/a> et <a href=\"https:\/\/cran.r-project.org\/web\/packages\/doMC\/index.html\">doMC<\/a><\/li>\n<li>Nous <em>pr\u00e9cisons<\/em> le nombre de CPUs disponible \u00e0 doMC <strong># N&rsquo;oubliez surtout pas cette \u00e9tape sinon l&rsquo;ex\u00e9cution se fera de mani\u00e8re s\u00e9quentielle!<\/strong><\/li>\n<li>Nous sp\u00e9cifions que la librairie <em>randomForest<\/em> doit \u00eatre initialis\u00e9e dans les contextes d&rsquo;ex\u00e9cution parall\u00e8les \u00e0 l&rsquo;aide de l&rsquo;option <strong>.packages<\/strong> de foreach<\/li>\n<li>Nous <em>fusionnons les r\u00e9sultats des diff\u00e9rents traitements parall\u00e8les<\/em> en passant la m\u00e9thode combine de randomForest \u00e0 l&rsquo;option <strong>.combine<\/strong> de foreach.<\/li>\n<\/ul>\n<p>Plut\u00f4t simple, non ? Et maintenant nous sommes assur\u00e9s de pouvoir faire croitre un nombre d&rsquo;arbre suffisant \u00e0 une saine exploration de notre jeu de donn\u00e9es tout en demeurant dans un d\u00e9lai computationnel raisonnable !<\/p>\n<p>La fusion des r\u00e9sultats des traitement individuels de foreach, bien que non n\u00e9cessaire <i>per se<\/i> puisque par d\u00e9faut foreach retournera une <em>liste de r\u00e9sultats<\/em>, peut se faire \u00e0 l&rsquo;aide de bon nombre de fonctions R communes telles que c (concat), cbind\/rbind ou encore \u00e0 l&rsquo;aide d&rsquo;une fonction sur mesure que nous aurons pr\u00e9alablement d\u00e9finie.<\/p>\n<p>Si vous n&rsquo;\u00eates toujours pas convaincus, laissez moi ajouter que la librairie <a href=\"https:\/\/cran.r-project.org\/web\/packages\/doMC\/index.html\">doMC<\/a> peut ais\u00e9ment \u00eatre remplac\u00e9e par une autre impl\u00e9mentation do* en fonction du type de distribution des t\u00e2ches qui vous int\u00e9resse.  Par exemple: de tr\u00e8s l\u00e9g\u00e8res modifications au code ci-haut permettraient \u00e0 <a href=\"https:\/\/cran.r-project.org\/web\/packages\/doMPI\/index.html\">doMPI<\/a> ou encore <a href=\"https:\/\/cran.r-project.org\/web\/packages\/doSNOW\/index.html\">doSNOW<\/a> de distribuer vos t\u00e2ches sur une grappe de calcul. Pas mal !<\/p>\n<p>Comme lecture de chevet, vous pourriez vous pencher sur <a href=\"https:\/\/cran.r-project.org\/web\/packages\/foreach\/vignettes\/nested.pdf\">l&rsquo;imbrication des boucles foreach<\/a> et\/ou l&rsquo;usage de l&rsquo;op\u00e9rateur <strong>when<\/strong> afin de pr\u00e9venir l&rsquo;\u00e9valuation d&rsquo;un sous ensemble de votre jeu de donn\u00e9es&#8230; Cet argument rappelera certainement le <i>if<\/i> des <em>list comprehensions<\/em> de Python.<\/p>\n<p>Alors allez-y, \u00e9pargner du temps r\u00e9el d&rsquo;ex\u00e9cution en distribuant vos t\u00e2ches ad\u00e9quatement et profitez du temps sauv\u00e9 pour explorer votre jeu de donn\u00e9es plus \u00e0 fond !<\/p>\n","protected":false},"excerpt":{"rendered":"<p>La derni\u00e8re fois que j&rsquo;ai abord\u00e9 ce sujet, je vous ai pr\u00e9sent\u00e9 une technique vraiment simple pour changer vos appels lapply en leur \u00e9quivalents parall\u00e8les mclapply. Mais bien que ce soit une modification extr\u00eamement simple \u00e0 impl\u00e9menter et qui donne d&rsquo;excellent gains en performance, celle-ci n\u00e9cessitait toutefois que votre code fasse d\u00e9j\u00e0 usage de lapply. Alors explorons une autre techinque simple pour introduire du traitement parall\u00e8le dans votre code source existant \u00e0 l&rsquo;aide des librairies foreach et doMC. La librairie <a href=\"https:\/\/bioinfo.iric.ca\/fr\/traitement-parallele-facile-avec-r-suite\/\"> [&#8230;]<\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"jetpack_post_was_ever_published":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":true,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2}},"categories":[32,24],"tags":[52,101],"class_list":["post-2483","post","type-post","status-publish","format-standard","hentry","category-performance-fr-2","category-langage-r","tag-multiprocessing","tag-test"],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/bioinfo.iric.ca\/fr\/wp-json\/wp\/v2\/posts\/2483","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/bioinfo.iric.ca\/fr\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/bioinfo.iric.ca\/fr\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/bioinfo.iric.ca\/fr\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/bioinfo.iric.ca\/fr\/wp-json\/wp\/v2\/comments?post=2483"}],"version-history":[{"count":6,"href":"https:\/\/bioinfo.iric.ca\/fr\/wp-json\/wp\/v2\/posts\/2483\/revisions"}],"predecessor-version":[{"id":2491,"href":"https:\/\/bioinfo.iric.ca\/fr\/wp-json\/wp\/v2\/posts\/2483\/revisions\/2491"}],"wp:attachment":[{"href":"https:\/\/bioinfo.iric.ca\/fr\/wp-json\/wp\/v2\/media?parent=2483"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/bioinfo.iric.ca\/fr\/wp-json\/wp\/v2\/categories?post=2483"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/bioinfo.iric.ca\/fr\/wp-json\/wp\/v2\/tags?post=2483"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}