{"id":2003,"date":"2016-03-14T15:37:08","date_gmt":"2016-03-14T19:37:08","guid":{"rendered":"http:\/\/bioinfo.iric.ca\/fr\/?p=2003"},"modified":"2016-03-14T16:22:33","modified_gmt":"2016-03-14T20:22:33","slug":"traitement-parallele-facile-avec-r","status":"publish","type":"post","link":"https:\/\/bioinfo.iric.ca\/fr\/traitement-parallele-facile-avec-r\/","title":{"rendered":"Traitement parall\u00e8le facile avec R"},"content":{"rendered":"<p>Poursuivant sur ma lanc\u00e9e d&rsquo;exploration de code \u00e0 haute performance, regardons aujourd&rsquo;hui comment ajouter du traitement parall\u00e8le dans vos scripts R.  Bien que plusieurs options existent pour parall\u00e9liser le traitement de vos donn\u00e9es, concentrons nous sur quelque chose de tr\u00e8s facile \u00e0 mettre en place pour commencer.<\/p>\n<p>Il y a quelques temps, j&rsquo;ai eu \u00e0 \u00e9crire un script ayant pour but de rouler un grand nombre de regressions logistiques (\u00e0 l&rsquo;aide du <a href=\"https:\/\/stat.ethz.ch\/R-manual\/R-devel\/library\/stats\/html\/glm.html\" target=\"_blank\">package glm<\/a>) dans un effort de mod\u00e9lisation de donn\u00e9es. Le tout produisait les r\u00e9sultats escompt\u00e9s mais prenait un temps non-n\u00e9gligeable puisqu&rsquo;un grand nombre de ces r\u00e9gressions devaient \u00eatre calcul\u00e9es (et optimis\u00e9es !). Par contre, le calcul de chacune des ces r\u00e9gression \u00e9tait ind\u00e9pendant des autres&#8230; Je me suis donc mis \u00e0 la recherche de solutions me permettant de parall\u00e9liser ce traitement.<\/p>\n<p>La solution retenue (et qui correspondait \u00e0 la structure de mon code) \u00e0 \u00e9t\u00e9 la simple substitution de la fonction <strong>lapply<\/strong> par une impl\u00e9mentation parall\u00e8le de celle-ci nomm\u00e9e <strong>mclapply<\/strong> et disponible \u00e0 travers le <a href=\"https:\/\/stat.ethz.ch\/R-manual\/R-devel\/library\/parallel\/html\/parallel-package.html\" target=\"_blank\">package parallel<\/a> (qui fait partie de la distribution de R depuis la version 2.14). Une simple substitution de fonction dans mon code \u00e0 coup\u00e9 mon de temps de calcul en 4 ! (Grosso modo.. :)).<\/p>\n<p>Et quand je parle de substitution simple, voici ce que j&rsquo;ai en t\u00eate:<br \/>\n<strong>Fragment de code original:<\/strong><\/p>\n<pre>\r\n<code class=\"r\">...\r\n\r\n\u0001gene_scores <- data.frame()\r\ngene_scores <- do.call('rbind', <strong>lapply<\/strong>(genes, function(x, data, formula) {\r\n\t\t\tyvar <- all.vars(formula)[1]\r\n\t\t\twork <- data[,c(yvar, x)]\r\n\t\t\tmodel <- glm (formula, data=work, family=binomial)\r\n\t\t\ts <- summary(model)\r\n\t\t\tcrossval <- CV_JPL(model, print.details=FALSE)\r\n\t\t\treturn(data.frame(gene=x, deviance=s$deviance, \r\n                                          acc.cv=crossval$acc.cv, \r\n                                          acc.internal=crossval$acc.internal))\r\n}, data=training, formula=formula))\r\n\r\n...\r\n<\/code><\/pre>\n<p><strong>Fragment parall\u00e9lis\u00e9:<\/strong><\/p>\n<pre>\r\n<code class=\"r\"><strong>library(parallel)<\/strong> # Il faut charger la librairie en m\u00e9moire !\r\n\r\n...\r\n\r\ngene_scores <- data.frame()\r\ngene_scores <- do.call('rbind', <strong>mclapply<\/strong>(genes, function(x, data, formula) {\r\n\t\t\tyvar <- all.vars(formula)[1]\r\n\t\t\twork <- data[,c(yvar, x)]\r\n\t\t\tmodel <- glm (formula, data=work, family=binomial)\r\n\t\t\ts <- summary(model)\r\n\t\t\tcrossval <- CV_JPL(model, print.details=FALSE)\r\n\t\t\treturn(data.frame(gene=x, deviance=s$deviance, \r\n                                          acc.cv=crossval$acc.cv, \r\n                                          acc.internal=crossval$acc.internal))\r\n}, data=training, formula=formula, <strong>mc.cores=4<\/strong>))\r\n\r\n...\r\n<\/code><\/pre>\n<p>J'ai mis les changement en gras pour qu'ils ressortent mieux.<br \/>\nEn gros, les voici:<br \/>\n1- charger la librairie en m\u00e9moire<br \/>\n2- modifier l'appel \u00e0 la fonction <code>lapply<\/code> pour <code>mclapply<\/code><br \/>\n3- sp\u00e9cifier le nombre de coeurs disponibles pour l'ex\u00e9cution \u00e0 l'aide du param\u00e8tre <code>mc.cores=X<\/code><\/p>\n<p>Le plus gros probl\u00e8me rencontr\u00e9 une fois ce changement effectu\u00e9 se trouve au niveau des \u00e9tapes de test\/d\u00e9buggage. Il est plus compliqu\u00e9 de stopper le traitement de fonctions parall\u00e9lis\u00e9es que leur versions non parall\u00e8les.  Mais bon, on peut facilement contourner ce l\u00e9ger d\u00e9sagr\u00e9ment en travaillant avec un jeu de donn\u00e9es r\u00e9duit ou encore en ne substituant lapply pour mclapply qu'au moment de lancer les calculs finaux ! <\/p>\n<p>En conclusion, voici une modification extr\u00eamement simple \u00e0 mettre en place si votre code fait appel \u00e0 lapply, alors il n'y a vraiment pas de raison de s'en passer ! Toutefois, si vous n'utilisez pas lapply dans votre code, bon nombre de librairies offrent la possibilit\u00e9 de parall\u00e9liser votre traitement de vos donn\u00e9es. Le duo <a href=\"https:\/\/cran.r-project.org\/web\/packages\/foreach\/index.html\">foreach<\/a> \/ <a href=\"https:\/\/cran.r-project.org\/web\/packages\/doMC\/index.html\">DoMC<\/a> vient rapidement \u00e0 l'esprit.  De plus, n'h\u00e9sitez pas \u00e0 jeter un oeil sur <a href=\"https:\/\/cran.r-project.org\/web\/views\/HighPerformanceComputing.html\">cette page<\/a> qui liste un grand nombre de ressources suppl\u00e9mentaires.<\/p>\n<p>\u00c0 la prochaine \ud83d\ude42<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Poursuivant sur ma lanc\u00e9e d&rsquo;exploration de code \u00e0 haute performance, regardons aujourd&rsquo;hui comment ajouter du traitement parall\u00e8le dans vos scripts R. Bien que plusieurs options existent pour parall\u00e9liser le traitement de vos donn\u00e9es, concentrons nous sur quelque chose de tr\u00e8s facile \u00e0 mettre en place pour commencer. Il y a quelques temps, j&rsquo;ai eu \u00e0 \u00e9crire un script ayant pour but de rouler un grand nombre de regressions logistiques (\u00e0 l&rsquo;aide du package glm) dans un effort de mod\u00e9lisation de <a href=\"https:\/\/bioinfo.iric.ca\/fr\/traitement-parallele-facile-avec-r\/\"> [&#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":[66],"class_list":["post-2003","post","type-post","status-publish","format-standard","hentry","category-performance-fr-2","category-langage-r","tag-multiprocessing-fr"],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/bioinfo.iric.ca\/fr\/wp-json\/wp\/v2\/posts\/2003","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=2003"}],"version-history":[{"count":5,"href":"https:\/\/bioinfo.iric.ca\/fr\/wp-json\/wp\/v2\/posts\/2003\/revisions"}],"predecessor-version":[{"id":2010,"href":"https:\/\/bioinfo.iric.ca\/fr\/wp-json\/wp\/v2\/posts\/2003\/revisions\/2010"}],"wp:attachment":[{"href":"https:\/\/bioinfo.iric.ca\/fr\/wp-json\/wp\/v2\/media?parent=2003"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/bioinfo.iric.ca\/fr\/wp-json\/wp\/v2\/categories?post=2003"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/bioinfo.iric.ca\/fr\/wp-json\/wp\/v2\/tags?post=2003"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}