]> AND Private Git Repository - these_gilles.git/blob - PRESENTATION-1/index.html
Logo AND Algorithmique Numérique Distribuée

Private GIT Repository
final
[these_gilles.git] / PRESENTATION-1 / index.html
1 <!DOCTYPE html><html xmlns="http://www.w3.org/1999/xhtml"><head><title>Algorithmes rapides sur GPU</title><meta name="generator" content="Hovercraft! 1.0 http://regebro.github.com/hovercraft"></meta><meta name="author" content="Gilles Perrot"></meta><link rel="stylesheet" href="css/hovercraft.css" media="all"></link><link rel="stylesheet" href="css/impressConsole.css" media="all"></link><link rel="stylesheet" href="css/highlight.css" media="all"></link><link rel="stylesheet" href="css/zulug5.css" media="all"></link><script type="text/javascript" src="https://c328740.ssl.cf1.rackcdn.com/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML"></script></head><body class="impress-not-supported"><div id="impress"><div class="step" step="0" id="titre" data-x="0" data-y="0"><h1 id="traitement-d-images-sur-gpu">TRAITEMENT D'IMAGES SUR GPU</h1><h2 id="algorithmes-rapides-pour-le-filtrage-et-la-segmentation-des-images-bruitees-sur-gpu">Algorithmes rapides pour le filtrage et la segmentation des images bruit&#xE9;es sur GPU.</h2><h3 id="gilles-perrot">Gilles Perrot</h3><h3 id="universite-de-franche-comte-institut-femto-st">Universit&#xE9; de Franche-Comt&#xE9;, Institut FEMTO-ST</h3><h3 id="departement-disc-equipe-and">D&#xE9;partement DISC - &#xE9;quipe AND</h3><h3 id="direction-r-couturier-s-domas">Direction  : R. Couturier &amp; S. Domas</h3></div><div class="step" step="1" data-x="1600" data-y="0"><h1 id="plan-de-la-presentation">PLAN DE LA PR&#xC9;SENTATION</h1><ol><li>Introduction - cadre des travaux<ul><li>Les GPUs (Graphical Processing Units)</li><li>G&#xE9;n&#xE9;ralit&#xE9;s sur le traitement d'image. Nos axes de recherche.</li></ul></li><li>La segmentation des images<ul><li>G&#xE9;n&#xE9;ralit&#xE9;s. Travaux de r&#xE9;f&#xE9;rence.</li><li>Parall&#xE9;lisation GPU d'un algorithme de segmentation de type <em>snake</em>.</li></ul></li><li>Le filtrage des images<ul><li>G&#xE9;n&#xE9;ralit&#xE9;s. Travaux de r&#xE9;f&#xE9;rence.</li><li>Optimisation pour GPU des filtres m&#xE9;dian et de convolution.</li><li>Conception d'un algorithme parall&#xE8;le de r&#xE9;duction de bruit par recherche des lignes de niveaux.</li></ul></li><li>Synth&#xE8;se et conclusion.</li></ol></div><div class="step" step="2" data-x="3200" data-y="0"><h1 id="introduction">INTRODUCTION</h1><p>Les GPUs - Les traitements d'image</p></div><div class="step" step="3" data-x="4800" data-y="0"><h1 id="id1">INTRODUCTION</h1><h2 id="les-gpus-ou-processeurs-graphiques">Les GPUs ou <em>Processeurs graphiques</em>.</h2><img src="img/gpucpu1.png" alt="" width="800px" height=""></img><ul><li>Processeurs <em>classiques</em> <strong>CPU</strong> : ex&#xE9;cution <strong>s&#xE9;quentielle</strong><ul><li>Quelques unit&#xE9;s de calcul ( les c&#x153;urs).</li></ul></li><li>Processeurs <em>graphiques</em> <strong>GPU</strong> : ex&#xE9;cution <strong>massivement parall&#xE8;le</strong><ul><li>Des centaines, voire millier, d'unit&#xE9;s de calcul, regroup&#xE9;es en quelques SMs (<em>Streaming Multiprocessors</em>).</li></ul></li></ul><div class="notes"><ul><li>La multiplication des c&#x153;urs dans les GPUs se fait au d&#xE9;triment des fonctions de contr&#xF4;le et de cache.</li><li>Seule la m&#xE9;moire <em>globale</em> est accessible par l'ensemble des fils d'ex&#xE9;cution (les <em>threads</em>) et ses performances sont faibles.</li><li>AU sein de la RAM il y a diff&#xE9;rents canaux vers diff&#xE9;rents types de m&#xE9;moires.</li><li>L'acc&#xE8;s efficace aux m&#xE9;moires  est contraignant.</li><li>Les &#xE9;changes de donn&#xE9;es entre le GPU et son h&#xF4;te CPU sont p&#xE9;nalisants.</li><li>Il est important de concevoir un partage &#xE9;quilibr&#xE9; des ressources au sein de chaque SM, pour permettre un niveau de parall&#xE9;lisme  &#xE9;lev&#xE9;, et donc d'envisager de bonnes performances.</li><li>La mise au point n'est pas ais&#xE9;e lorsque des centaines de milliers de threads concourent &#xE0; l'ex&#xE9;cution d'une t&#xE2;che.</li></ul></div></div><div class="step" step="4" data-x="6400" data-y="0"><h1 id="id2">INTRODUCTION</h1><h2 id="le-traitement-des-images">Le traitement des images</h2><ul><li>L'accroissement des capacit&#xE9;s de calcul a suivi l'augmentation des r&#xE9;solutions d'images.</li><li>Les traitements envisag&#xE9;s sur les images sont de plus en plus &#xE9;volu&#xE9;s ( traitements de haut niveau ) et requi&#xE8;rent souvent un temps de calcul accru.</li><li>L'architecture parall&#xE8;le particuli&#xE8;re des GPUs a permis d'am&#xE9;liorer consid&#xE9;rablement les performances de certaines classes d'algorithme et fait esp&#xE9;rer par ailleurs des acc&#xE9;l&#xE9;rations importantes.</li></ul><div class="notes"><ul><li>La croissance des capacit&#xE9;s de calcul des GPUs &#xE0; &#xE9;t&#xE9; beaucoup plus forte que celle des CPUs.</li><li><strong>Les travaux pr&#xE9;sent&#xE9;s ici sont une contribution &#xE0; cette recherche de performance.</strong></li></ul></div></div><div class="step" step="5" data-x="8000" data-y="0"><h1 id="id3">INTRODUCTION</h1><h2 id="id4">Le traitement des images</h2><ul><li>Beaucoup d'applications int&#xE8;grent des traitements d'images num&#xE9;riques.</li><li>Les capteurs num&#xE9;riques et les conditions d'acquisition sont &#xE0; l'origine de perturbations (bruits).</li><li>Les hautes r&#xE9;solutions sont souvent obtenues &#xE0; faible flux de photons, dont les variations engendrent du bruit.</li><li>La segmentation repr&#xE9;sente aussi un enjeu crucial, mais aucun algorithme universel n'a encore &#xE9;t&#xE9; &#xE9;labor&#xE9;.</li></ul><div class="notes"><ul><li>les bruits d&#xE9;gradent l'image de la sc&#xE8;ne id&#xE9;ale et peuvent en fausser ou compliquer l'interpr&#xE9;tation.</li><li>on recense plus de 4000 algorithmes de segmentation</li><li>La segmentation intervient dans beaucoup d'applications : du tracking &#xE0; la d&#xE9;tection ou &#xE0; l'extraction de caract&#xE9;ristiques diverses.</li><li>Mais aujourd'hui encore, une bonne segmentation est celle qui permet d'extraire ce que l'on attend =&gt; l'algorithme d&#xE9;pend du probl&#xE8;me.</li></ul></div></div><div class="step" step="6" data-x="9600" data-y="0"><h1 id="id5">INTRODUCTION</h1><h2 id="traitements-d-images-de-haut-niveau">Traitements d'images de haut niveau</h2><ol><li><strong>Pr&#xE9;-traiter</strong> et effectuer les traitements de haut niveau sur des images <em>am&#xE9;lior&#xE9;es</em>.<ul><li>r&#xE9;duction, <em>a priori</em>, du co&#xFB;t des traitements de haut niveau.</li><li>les pr&#xE9;traitements ont eux aussi un co&#xFB;t, en temps de calcul et potentiellement en information.</li></ul></li><li><strong>Ne pas pr&#xE9;-traiter</strong> et effectuer les traitements de haut niveau sur les images bruit&#xE9;es.<ul><li>pas de perte d'information due au pr&#xE9;-traitement.</li><li>les traitements de haut niveau sont, <em>a priori</em>, plus co&#xFB;teux.</li></ul></li></ol><div class="notes"><ul><li>Certains algo (LNIV) peuvent &#xEA;tre consid&#xE9;r&#xE9;s comme pr&#xE9;-traitement ou comme haut-niveau selon le point de vue et la classe d'algorithme.</li></ul></div></div><div class="step" step="7" data-x="11200" data-y="0"><h1 id="id6">INTRODUCTION</h1><h2 id="axes-des-travaux-presentes">Axes des travaux pr&#xE9;sent&#xE9;s</h2><p><strong>Segmentation : acc&#xE9;l&#xE9;rer le traitement de haut niveau</strong></p><blockquote><ul><li>La segmentation consiste &#xE0; identifier des zones homog&#xE8;nes dans une image.</li><li>Algorithme de segmentation d'images bruit&#xE9;es par contours actifs, de la classe des  <em>snakes</em>.</li><li>Conception d'une impl&#xE9;mentation avec adaptation de la technique d'optimisation.</li></ul></blockquote><p><strong>Filtrage : acc&#xE9;l&#xE9;rer les pr&#xE9;-traitements</strong></p><blockquote><p>R&#xE9;duction de bruit additif gaussien, suivant deux m&#xE9;thodes de conception  :</p><blockquote><ul><li>algorithme original, con&#xE7;u sp&#xE9;cifiquement pour GPU, conjointement &#xE0; son impl&#xE9;mentation.</li><li>algorithmes existants, o&#xF9; l'effort de conception ne peut porter que sur l'impl&#xE9;mentation : filtres m&#xE9;dian et de convolution.</li></ul></blockquote></blockquote></div><div class="step" step="8" data-x="12800" data-y="0"><h1 id="id7">INTRODUCTION</h1><h2 id="images-traitees">Images trait&#xE9;es</h2><ul><li>Nous nous sommes focalis&#xE9;s sur les <em>images naturelles</em> :</li></ul><blockquote><ul><li>r&#xE9;alis&#xE9;es en lumi&#xE8;re naturelle, en int&#xE9;rieur ou en ext&#xE9;rieur,</li><li>prises avec un dispositif standard (CMOS, CCD).</li></ul></blockquote><ul><li>Les traitements que nous pr&#xE9;sentons ici op&#xE8;rent sur des images en
2 niveau de gris (8 ou 16 bits).</li></ul><div class="notes"><ul><li>Toutefois, la plupart des algorithmes que nous proposons s'&#xE9;tend simplement &#xE0; d'autres types d'images, comme les images en couleur ou celles issues des imageries ultrasonore ou RADAR &#xE0; ouverture synth&#xE9;tique.</li></ul></div></div><div class="step" step="9" data-x="14400" data-y="0"><h1 id="la-segmentation-des-images">LA SEGMENTATION DES IMAGES</h1><p>Segmentation par contour actif</p></div><div class="step" step="10" data-x="16000" data-y="0"><h1 id="segmentation-par-contour-actif">SEGMENTATION PAR CONTOUR ACTIF</h1><h2 id="id8">Introduction</h2><p>La segmentation par contour actif regroupe des m&#xE9;thodes it&#xE9;ratives tendant &#xE0; faire converger, par d&#xE9;formations successives, une courbe param&#xE9;trique (contour) selon un crit&#xE8;re d'homog&#xE9;n&#xE9;it&#xE9; pr&#xE9;-&#xE9;tabli :</p><blockquote><ul><li>La classe d'algorithmes la plus impl&#xE9;ment&#xE9;e sur GPU est celle des <strong>level-set</strong>, essentiellement dans sa variante <em>bande &#xE9;troite</em>.</li><li>La classe des <strong>snakes</strong> n'est impl&#xE9;ment&#xE9;e sur GPU qu'au travers la variante GVF (Gradient Vector Flow).</li></ul></blockquote><img src="img/l7-gvf.png" alt="" width="600px" height=""></img>&#xC0;  gauche : Level-set, &#xE9;volution du contour, en rouge (d'apr&#xE8;s J. Sethian). &#xC0; droite : visualisation du champ de force d'un <em>snake</em> GVF (d'apr&#xE8;s C. Xu).<div class="notes"><ul><li>Le domaine m&#xE9;dical rec&#xE8;le la quasi totalit&#xE9; des impl&#xE9;mentations GPU d'algorithmes de segmentation.</li><li>Nombre d'entre elles concernent des traitements effectu&#xE9;s en 3D par n&#xE9;cessit&#xE9;, o&#xF9; l'emploi du GPU s'impose assez naturellement.</li></ul></div></div><div class="step" step="11" data-x="17600" data-y="0"><h1 id="id9">SEGMENTATION PAR CONTOUR ACTIF</h1><h2 id="travaux-de-reference-level-set">Travaux de r&#xE9;f&#xE9;rence (level-set)</h2><p>L'impl&#xE9;mentation de Roberts <em>et al.</em>  du <em>level-set</em> &#xE0; <em>bande &#xE9;troite</em> est actuellement la plus performante et parvient &#xE0; segmenter des images d'IRM</p><blockquote><ul><li>3D, de 256x256x256 pixels, sur GTX280, en <strong>11 000 ms</strong></li></ul></blockquote><img src="img/brain3D.png" alt="" width="800px" height=""></img>&#xC0;  gauche : &#xE9;volution du contour pour une <em>tranche</em> avec, en bleu, les zones actives. &#xC0; droite : visualisation  en 3D de la segmentation compl&#xE8;te.</div><div class="step" step="12" data-x="19200" data-y="0"><h1 id="id10">SEGMENTATION PAR CONTOUR ACTIF</h1><h2 id="travaux-de-reference-snake">Travaux de r&#xE9;f&#xE9;rence (snake)</h2><ul><li>La r&#xE9;f&#xE9;rence est l'impl&#xE9;mentation <em>snake GVF</em>  de Smistad <em>et al.</em> qui parvient &#xE0; segmenter des images d'IRM</li></ul><blockquote><ul><li>2D, de 512x512 pixels, sur C2070, en <strong>41 ms</strong>.</li><li>3D, de 256x256x256 pixels, sur C2070, en <strong>7151 ms</strong></li></ul></blockquote><img src="img/brain3D-gvf.png" alt="" width="600px" height=""></img>&#xC0;  gauche : une image 2D d'IRM. &#xC0; droite : visualisation  en 3D de la segmentation compl&#xE8;te.<div class="notes"><ul><li>&#xC0; notre connaissance, aucune publication ne d&#xE9;crit d'impl&#xE9;mentation de <em>snake</em> polygonal ou de <em>snake</em> orient&#xE9; r&#xE9;gion.</li></ul></div></div><div class="step" step="13" data-x="20800" data-y="0"><h1 id="id11">SEGMENTATION PAR CONTOUR ACTIF</h1><h2 id="snake-polygonal-oriente-region-principe"><em>Snake</em> polygonal orient&#xE9; r&#xE9;gion (principe)</h2><table cellpadding="0" cellspacing="0" class="columns"><tbody><tr><td><img src="img/snake-modele.png" alt="" width="350px" height=""></img></td><td><ul><li>L'objectif est de d&#xE9;terminer le contour le plus <em>vraisemblable</em> (nombre et positions des n&#x153;uds).</li><li>Le crit&#xE8;re de vraisemblance g&#xE9;n&#xE9;ralis&#xE9;e est, dans le cas gaussien :$$GL = \frac{1}{2}\left[ n_B.log\left(\sigma_B^2\right) + n_T.log\left(\sigma_T^2\right)\right]$$</li></ul></td></tr></tbody></table><ul><li>Les deux r&#xE9;gions, int&#xE9;rieure et ext&#xE9;rieure (T et B), sont prises en compte dans l'&#xE9;valuation du contour.</li><li>Les variances \(\sigma^2\) doivent &#xEA;tre calcul&#xE9;es pour chaque &#xE9;tat du contour, ce qui est <strong>tr&#xE8;s co&#xFB;teux</strong>.</li></ul><div class="notes"><ul><li>Cela permet d'extraire des formes aux contours mal d&#xE9;finis, en raison d'un fort niveau de bruit par exemple.</li></ul></div></div><div class="step" step="14" data-x="22400" data-y="0"><h1 id="id12">SEGMENTATION PAR CONTOUR ACTIF</h1><h2 id="id13"><em>Snake</em> polygonal orient&#xE9; r&#xE9;gion (principe)</h2><img src="img/snake-modele.png" alt="" width="350px" height=""></img><ul><li>Chesnaud <em>et al.</em> ont montr&#xE9; comment remplacer la sommation 3D par une <strong>sommation 2D</strong> le long du contour.</li><li>Implique le <strong>pr&#xE9;-calcul</strong> des trois images cumul&#xE9;es$$S_1(i,j)=\sum_{x=0}^jx \text{ , }  S_x(i,j)=\sum_{x=0}^jI(i,x) \text{ et  } S_{x^2}(i,j)=\sum_{x=0}^jI(i,x)^2$$</li></ul><div class="notes"><ul><li>Les valeurs des &#xE9;l&#xE9;ments de ces images cumul&#xE9;es permettent de calculer la <strong>contribution</strong> de chaque pixel du contour, puis de chaque segment, aux calculs des variances.</li></ul></div></div><div class="step" step="15" data-x="24000" data-y="0"><h1 id="id14">SEGMENTATION PAR CONTOUR ACTIF</h1><h2 id="snake-polygonal-oriente-region-algo-cpu"><em>Snake</em> polygonal orient&#xE9; r&#xE9;gion (algo CPU)</h2><img src="img/cochons-it0-it1.png" alt="" width="" height="300px"></img><p><strong>It&#xE9;ration 1</strong></p><blockquote><ol><li>Le contour initial est rectangulaire ( 4 n&#x153;uds )</li><li>On d&#xE9;place successivement les 4 n&#x153;uds jusqu'&#xE0; ce que plus aucun nouveau d&#xE9;placement ne provoque l'am&#xE9;lioration du crit&#xE8;re.</li></ol></blockquote></div><div class="step" step="16" data-x="25600" data-y="0"><h1 id="id15">SEGMENTATION PAR CONTOUR ACTIF</h1><h2 id="id16"><em>Snake</em> polygonal orient&#xE9; r&#xE9;gion (algo CPU)</h2><img src="img/cochons-it21-it22.png" alt="" width="" height="300px"></img><p><strong>It&#xE9;ration 2</strong></p><blockquote><ol><li>Ajout de n&#x153;uds au milieu des segments suffisamment grands.</li><li>On recommence &#xE0; &#xE9;valuer les d&#xE9;placements successifs des n&#x153;uds.</li></ol></blockquote></div><div class="step" step="17" data-x="27200" data-y="0"><h1 id="id17">SEGMENTATION PAR CONTOUR ACTIF</h1><h2 id="id18"><em>Snake</em> polygonal orient&#xE9; r&#xE9;gion (algo CPU)</h2><img src="img/cochons-it4-it5.png" alt="" width="" height="300px"></img><p><strong>It&#xE9;rations 4 et 5</strong></p></div><div class="step" step="18" data-x="28800" data-y="0"><h1 id="id19">SEGMENTATION PAR CONTOUR ACTIF</h1><h2 id="id20"><em>Snake</em> polygonal orient&#xE9; r&#xE9;gion (algo CPU)</h2><img src="img/im014.png" alt="" width="" height="400px"></img>Image de 512x512 : contour final de 256 n&#x153;uds en 14ms.<ul><li>Les r&#xE9;sultats de segmentation d&#xE9;pendent des param&#xE8;tres de la s&#xE9;quence d'optimisation (pas des d&#xE9;placements, contour initial, seuil d'ajout des n&#x153;uds)</li></ul></div><div class="step" step="19" data-x="30400" data-y="0"><h1 id="id21">SEGMENTATION PAR CONTOUR ACTIF</h1><h2 id="id22"><em>Snake</em> polygonal orient&#xE9; r&#xE9;gion (algo CPU)</h2><img src="img/snakegpu1.png" alt="" width="" height="400px"></img>Image de 4000x4000 : contour final de 447 n&#x153;uds en 700ms.</div><div class="step" step="20" data-x="32000" data-y="0"><h1 id="id23">SEGMENTATION PAR CONTOUR ACTIF</h1><h2 id="parallelisation-du-snake-polygonal-sur-gpu">Parall&#xE9;lisation du <em>Snake</em> polygonal sur GPU</h2><p>Identification des fonctions co&#xFB;teuses</p><img src="img/algosnake1.png" alt="" width="" height="500px"></img></div><div class="step" step="21" data-x="33600" data-y="0"><h1 id="id24">SEGMENTATION PAR CONTOUR ACTIF</h1><h2 id="id25">Parall&#xE9;lisation du <em>Snake</em> polygonal sur GPU</h2><p>D&#xE9;tail de la fonction de calcul du crit&#xE8;re GL</p><img src="img/algosnake2b.png" alt="" width="" height="500px"></img></div><div class="step" step="22" data-x="35200" data-y="0"><h1 id="id26">SEGMENTATION PAR CONTOUR ACTIF</h1><h2 id="id27">Parall&#xE9;lisation du <em>Snake</em> polygonal sur GPU</h2><img src="img/snake-pairimpair.png" alt="" width="800px" height=""></img><div class="notes"><ul><li>Pour un n&#x153;ud et un pas de d&#xE9;placement donn&#xE9;s, on &#xE9;value <strong>en parall&#xE8;le</strong> 8 positions voisines, soit 16 segments distincts.</li><li>Pour &#xE9;viter les oscillations et <em>coller</em> &#xE0; l'algorithme s&#xE9;quentiel, on distingue les n&#x153;uds d'indices pairs et impairs.</li><li>On &#xE9;value <strong>en parall&#xE8;le</strong> l'ensemble des d&#xE9;placements &#xE9;ventuels de tous les n&#x153;uds de m&#xEA;me parit&#xE9;.</li></ul></div></div><div class="step" step="23" data-x="36800" data-y="0"><h1 id="id28">SEGMENTATION PAR CONTOUR ACTIF</h1><h2 id="id29">Parall&#xE9;lisation du <em>Snake</em> polygonal sur GPU</h2><p><strong>Structure des donn&#xE9;es</strong> (n&#x153;uds pairs)</p><img src="img/16segments.png" alt="" width="800px" height=""></img><div class="notes"><ul><li>r&#xE8;gle 1 thread par pixel</li></ul></div></div><div class="step" step="24" data-x="38400" data-y="0"><h1 id="id30">SEGMENTATION PAR CONTOUR ACTIF</h1><h2 id="id31">Parall&#xE9;lisation du <em>Snake</em> polygonal sur GPU</h2><p><strong>Obtention du crit&#xE8;re</strong></p><ul><li>Parall&#xE9;lisation :  1 thread par pixel.</li><li>Une seule taille de segment : la taille du plus long.</li><li>Bourrage avec des threads inactifs pour les segments plus courts.</li><li>Calcul r&#xE9;alis&#xE9; en 3 &#xE9;tapes par 3 fonctions parall&#xE8;les GPU (<em>kernels</em>)</li></ul><blockquote><ol><li>Calculs r&#xE9;alisables <strong>au niveau bloc</strong> : coordonn&#xE9;es des pixels, lecture des param&#xE8;tres dans les images cumul&#xE9;es, sommes partielles des contributions des segments.</li><li><strong>R&#xE9;ductions</strong> : calcul final des contributions des segments.</li><li>Calcul des valeurs du crit&#xE8;re pour chaque contour &#xE9;valu&#xE9;. S&#xE9;lection du meilleur contour.</li></ol></blockquote><div class="notes"><ul><li>les r&#xE9;duction consistent &#xE0; sommer, pour chaque segment les contributions partielles par bloc calcul&#xE9;es au 1</li></ul></div></div><div class="step" step="25" data-x="40000" data-y="0"><h1 id="id32">SEGMENTATION PAR CONTOUR ACTIF</h1><h2 id="id33">Parall&#xE9;lisation du <em>Snake</em> polygonal sur GPU</h2><p><strong>Propri&#xE9;t&#xE9;s de l'impl&#xE9;mentation</strong></p><blockquote><ul><li>Conservation des donn&#xE9;es en m&#xE9;moire GPU.</li><li>Les images cumul&#xE9;es sont calcul&#xE9;es en parall&#xE8;le.</li><li>Abandon de l'algorithme de Bresenham pour la discretisation des segments.</li><li>Trop peu de calculs &#xE0; effectuer. Peu de threads dans la grille.</li><li>Pas de coalescence possible dans les acc&#xE8;s &#xE0; la m&#xE9;moire globale.</li><li>Emploi de la m&#xE9;moire partag&#xE9;e.</li></ul></blockquote><div class="notes"><ul><li>Un seul entier est &#xE9;chang&#xE9; entre le CPU et le GPU &#xE0; chaque it&#xE9;ration.</li><li>image cumul&#xE9;es par une adaptation de la m&#xE9;thode des sommes de pr&#xE9;fixes.</li><li>Abandon  Bresenham Possible car parcours unidirectionnel du contour.</li><li>Trop peu de calculs ne permet pas de masquer les latences.</li><li>Pas de coalescence possible dans les acc&#xE8;s &#xE0; la m&#xE9;moire globale car la g&#xE9;om&#xE9;trie des segments varie.</li><li>m&#xE9;moire partag&#xE9;e &#xE0; cause des r&#xE9;ductions.</li></ul></div></div><div class="step" step="26" data-x="41600" data-y="0"><h1 id="id34">SEGMENTATION PAR CONTOUR ACTIF</h1><h2 id="id35">Parall&#xE9;lisation du <em>Snake</em> polygonal sur GPU</h2><p><strong>Performances de l'impl&#xE9;mentation</strong></p><img src="img/perfs-snake.png" alt="" width="600px" height=""></img><img src="img/perfs-snake-img.png" alt="" width="600px" height=""></img></div><div class="step" step="27" data-x="43200" data-y="0"><h1 id="id36">SEGMENTATION PAR CONTOUR ACTIF</h1><h2 id="id37">Parall&#xE9;lisation du <em>Snake</em> polygonal sur GPU</h2><p><strong>Conclusion</strong></p><ul><li>Premi&#xE8;re et seule impl&#xE9;mentation &#xE0; ce jour.</li><li>Performances int&#xE9;ressantes pour les grandes images. 1OO MP en moins de 0,6 seconde.</li><li>Temps de calcul tr&#xE8;s d&#xE9;pendant du contenu de l'image.</li><li>Le GPU n'est pas employ&#xE9; de mani&#xE8;re optimale : r&#xE9;ductions, threads inactifs, non coalescence.</li><li>Le GPU apporte un gain important sur les premi&#xE8;res it&#xE9;rations, quand les segments sont grands.</li><li>Initialisation optionnelle par maximum de vraisemblance. Acc&#xE9;l&#xE9;ration jusqu'&#xE0; x15 avec de petites cibles.</li></ul></div><div class="step" step="28" data-x="44800" data-y="0"><h1 id="le-filtrage-des-images">LE FILTRAGE DES IMAGES</h1><p>Filtre m&#xE9;dian - Filtres de convolution - Filtre par lignes de niveaux</p></div><div class="step" step="29" data-x="46400" data-y="0"><h1 id="id38">LE FILTRAGE DES IMAGES</h1><h2 id="filtre-median">Filtre m&#xE9;dian</h2></div><div class="step" step="30" data-x="48000" data-y="0"><h1 id="id39">LE FILTRAGE DES IMAGES</h1><h2 id="filtre-median-principe">Filtre m&#xE9;dian : principe</h2><img src="img/median-principe.png" alt="" width="600px" height=""></img><p>La valeur de sortie d'un pixel est la <strong>m&#xE9;diane</strong> des valeurs de son voisinage.</p><ul><li>Bonne r&#xE9;duction de bruits gaussien et <em>poivre &amp; sel</em></li><li>Valeurs de sortie appartenant au voisinage.</li><li>Op&#xE9;ration de s&#xE9;lection co&#xFB;teuse (tri).</li><li>Usages fr&#xE9;quents avec des petites fen&#xEA;tres (de 3x3 &#xE0; 7x7).</li><li>Quelques applications avec de grandes fen&#xEA;tres (au del&#xE0; de 21x21).</li></ul></div><div class="step" step="31" data-x="49600" data-y="0"><h1 id="id40">LE FILTRAGE DES IMAGES</h1><h2 id="filtre-median-usage">Filtre m&#xE9;dian : usage</h2><table cellpadding="0" cellspacing="0"><thead><tr><th><img src="img/airplane_sap25.png" alt="" width="" height=""></img></th><th><img src="img/airplane_sap25_med5.png" alt="" width="" height=""></img></th><th><img src="img/airplane_sap25_med3_it2.png" alt="" width="" height=""></img></th></tr></thead><tbody><tr><td><p>Bruit <em>poivre &amp; sel</em> 25%</p></td><td><p>M&#xE9;dian 5x5</p></td><td><p>M&#xE9;dian 3x3 - 2 passes</p></td></tr></tbody></table></div><div class="step" step="32" data-x="51200" data-y="0"><h1 id="id41">LE FILTRAGE DES IMAGES</h1><h2 id="filtre-median-gpu-travaux-de-reference">Filtre m&#xE9;dian GPU : Travaux de r&#xE9;f&#xE9;rence</h2><ul><li>Sanchez <em>et al.</em> ont propos&#xE9; le <strong>PCMF</strong> et l'ont compar&#xE9;, sur C2075, avec les impl&#xE9;mentations GPU de r&#xE9;f&#xE9;rence pour une image 8 bits de 512x512 (d&#xE9;bit max. <strong>80 MP/s</strong>) :</li></ul><blockquote><ul><li><strong>ArrayFire</strong>, biblioth&#xE8;que commerciale, d&#xE9;bit max. <strong>185 MP/s</strong></li><li><strong>BVM</strong> parall&#xE9;lis&#xE9; par Kachelrie&#xDF;, d&#xE9;bit max. <strong>110 MP/s</strong></li></ul></blockquote><img src="img/compar-median2.png" alt="" width="500px" height=""></img><div class="notes"><ul><li>PCMF : Parallel (Complementary Cumulative Derivative Function) Median Filter (histogrammes cumulatifs)</li><li>CTMF : CPU &#xE0; temps constant</li></ul></div></div><div class="step" step="33" data-x="52800" data-y="0"><h1 id="id42">LE FILTRAGE DES IMAGES</h1><h2 id="id43">Filtre m&#xE9;dian GPU : Travaux de r&#xE9;f&#xE9;rence</h2><p>Emploi de la <strong>m&#xE9;moire partag&#xE9;e</strong> pour pr&#xE9;-charger les valeurs utiles &#xE0; chaque bloc de threads.</p><img src="img/shmemhalo.png" alt="" width="800px" height=""></img></div><div class="step" step="34" data-x="54400" data-y="0"><h1 id="id44">LE FILTRAGE DES IMAGES</h1><h2 id="optimisation-du-filtre-median-gpu">Optimisation du filtre m&#xE9;dian GPU</h2><p>Transferts des donn&#xE9;es optimis&#xE9;s</p><img src="img/CPU-GPU-memcpy.png" alt="" width="750px" height=""></img><img src="img/transferts-mem.png" alt="" width="650px" height=""></img><div class="notes"><p>On gagne de 13 &#xE0; 43 % sur les temps de transfert.</p></div></div><div class="step" step="35" data-x="56000" data-y="0"><h1 id="id45">LE FILTRAGE DES IMAGES</h1><h2 id="id46">Optimisation du filtre m&#xE9;dian GPU</h2><img src="img/CPU-GPU-memcpy-dummykernel.png" alt="" width="750px" height=""></img><p>D&#xE9;bits maximums effectifs, en MP/s, pour des images en 8 et 16 bits, incluant les transferts optimis&#xE9;s (C2070).</p><blockquote><img src="img/debit-max-2070.png" alt="" width="300px" height=""></img></blockquote><p><strong>Rappel :</strong> PCMF : 80 MP/s - BVM : 110 MP/s - ArrayFire : 185 MP/s</p><div class="notes"><p>&#xE7;a laisse environ 80ms pour faire un tri de 9 valeurs sur une image de 4096x4096</p></div></div><div class="step" step="36" data-x="57600" data-y="0"><h1 id="id47">LE FILTRAGE DES IMAGES</h1><h2 id="id48">Optimisation du filtre m&#xE9;dian GPU</h2><p><strong>S&#xE9;lection de la m&#xE9;diane</strong></p><blockquote><ul><li>Emploi exclusif des <strong>registres</strong> pour charger les valeurs utiles.</li><li>Limitations &#xE0; 63 registres par thread et 32 K par bloc de threads.</li><li>Envisageable pour les m&#xE9;dians de petite taille (jusqu'&#xE0; 7x7 avec 1 thread/pixel).</li><li>Exploitation des recouvrements entre fen&#xEA;tres de pixels voisins.</li></ul></blockquote></div><div class="step" step="37" data-x="59200" data-y="0"><h1 id="id49">LE FILTRAGE DES IMAGES</h1><h2 id="id50">Optimisation du filtre m&#xE9;dian GPU</h2><p><strong>S&#xE9;lection de la m&#xE9;diane</strong> (par oubli)</p><table cellpadding="0" cellspacing="0" class="columns"><tbody><tr><td><p>Bonnes performances envisag&#xE9;es :</p><blockquote><ul><li>&#xC9;conomie de registres.</li><li>&#xC9;vite le tri complet.</li></ul></blockquote></td><td><img src="img/forgetful_selection.png" alt="" width="" height="500px"></img></td></tr></tbody></table></div><div class="step" step="38" data-x="60800" data-y="0"><h1 id="id51">LE FILTRAGE DES IMAGES</h1><h2 id="id52">Optimisation du filtre m&#xE9;dian GPU</h2><p><strong>Exploitation des recouvrements</strong></p><img src="img/recouvrement5.png" alt="" width="800px" height=""></img><p><strong>Int&#xE9;r&#xEA;t :</strong>  &#xC9;conomie de registres - chaque thread traite 2 pixels.</p><div class="notes"><ul><li>chaque thread utilise plus de registres</li><li>mais sur un bloc, en adaptant la taille du bloc, on &#xE9;conomise k+1 registres par paire de pixels.</li></ul></div></div><div class="step" step="39" data-x="62400" data-y="0"><h1 id="id53">LE FILTRAGE DES IMAGES</h1><h2 id="id54">Optimisation du filtre m&#xE9;dian GPU</h2><p><strong>Masquage des latences</strong></p><ul><li>Acc&#xE8;s &#xE0; la m&#xE9;moire globale : 2 pixels par thread.</li><li>Instruction Level Parallelism (ILP) : Ordre des instructions minimisant l'interd&#xE9;pendance.<img src="img/bitonic.png" alt="" width="" height="300px"></img>Identification des extrema dans le vecteur initial d'un m&#xE9;dian 5x5</li></ul><div class="notes"><ul><li>au del&#xE0; de 2 pixels par thread, le gain sur les latences est compens&#xE9; par la perte sur le calcul / niveau de parall&#xE8;lisme.</li><li>ILP maximis&#xE9;e en appliquant une m&#xE9;thode simple; utilis&#xE9;e par ex. dans la technique des r&#xE9;seaux de tri bitoniques.</li></ul></div></div><div class="step" step="40" data-x="64000" data-y="0"><h1 id="id55">LE FILTRAGE DES IMAGES</h1><h2 id="performances-du-filtre-median-gpu-propose-prmf">Performances du filtre m&#xE9;dian GPU propos&#xE9; (PRMF)</h2><img src="img/perf-median.png" alt="" width="650px" height=""></img></div><div class="step" step="41" data-x="65600" data-y="0"><h1 id="id56">LE FILTRAGE DES IMAGES</h1><h2 id="id57">Performances du filtre m&#xE9;dian GPU propos&#xE9; (PRMF)</h2><p>Image 512x512</p><blockquote><img src="img/comp512.png" alt="" width="" height="200px"></img></blockquote><p>Image 4096x4096</p><blockquote><img src="img/comp4k.png" alt="" width="" height="200px"></img></blockquote></div><div class="step" step="42" data-x="67200" data-y="0"><h1 id="id58">LE FILTRAGE DES IMAGES</h1><h2 id="le-filtre-median-gpu">Le filtre m&#xE9;dian GPU</h2><p><strong>Conclusion</strong></p><blockquote><ul><li>Pas d'utilisation de la m&#xE9;moire partag&#xE9;e.</li><li>D&#xE9;bit global am&#xE9;lior&#xE9; de x7 &#xE0; x10, proche du maximum.</li><li>D&#xE9;bit de calcul atteignant <strong>5,3 GP/s</strong>.</li><li>M&#xE9;dian jusqu'au 9x9 sur C2070, 21x21 sur K40.</li><li>Cr&#xE9;ation d'une application web g&#xE9;n&#xE9;rant les codes sources.</li><li>Utilis&#xE9; pour le pr&#xE9;-traitement d'images de cristallographie  au synchrotron <strong>SPring-8</strong> (Japon).</li></ul></blockquote><img src="img/SPring8.png" alt="" width="" height="200px"></img></div><div class="step" step="43" data-x="68800" data-y="0"><h1 id="id59">LE FILTRAGE DES IMAGES</h1><h2 id="les-filtres-de-convolution">Les filtres de convolution</h2></div><div class="step" step="44" data-x="70400" data-y="0"><h1 id="id60">LE FILTRAGE DES IMAGES</h1><h2 id="les-filtres-de-convolution-generalites">Les filtres de convolution : g&#xE9;n&#xE9;ralit&#xE9;s</h2><p><strong>Principe</strong></p><blockquote>$$I_{out}(x, y) = \left(I_{in} * h\right) = \sum_{(i &lt; H)} \sum_{(j &lt; L)}I_{in}(x-j, y-i)h(j,i)$$</blockquote><p><strong>Usage, selon les valeurs du masque h</strong></p><blockquote><ul><li>r&#xE9;duction de bruit,</li><li>d&#xE9;tection de bords,...</li></ul></blockquote><div class="notes"><ul><li>selon h --&gt; convo s&#xE9;parable ou non s&#xE9;parable</li></ul></div></div><div class="step" step="45" data-x="72000" data-y="0"><h1 id="id61">LE FILTRAGE DES IMAGES</h1><h2 id="les-filtres-de-convolution-gpu">Les filtres de convolution GPU</h2><p>Le fabricant Nvidia propose la plus rapide des impl&#xE9;mentations connue :</p><p>Convolution <strong>non s&#xE9;parable</strong> sur image de 2048x2048, masque h de 5x5, sur <strong>GTX280</strong>.</p><ul><li>D&#xE9;bit global : <strong>945 MP/s</strong>.</li><li>D&#xE9;bit de calcul : <strong>3,00 GP/s</strong></li></ul></div><div class="step" step="46" data-x="73600" data-y="0"><h1 id="id62">LE FILTRAGE DES IMAGES</h1><h2 id="id63">Les filtres de convolution GPU</h2><p>Exploitation des recouvrements</p><blockquote><ul><li>un seul acc&#xE8;s m&#xE9;moire par pixel, m&#xE9;morisation en registre.</li><li>mise &#xE0; jour de tous les calculs concern&#xE9;s</li></ul></blockquote><img src="img/convoOverlap2.png" alt="" width="400px" height=""></img><p>Application des techniques pr&#xE9;sent&#xE9;es pour le filtre m&#xE9;dian :</p><ul><li>Optimum &#xE0; 8 pixels par thread.</li><li>D&#xE9;bit global : <strong>966 MP/s</strong>.</li><li>D&#xE9;bit de calcul : <strong>3,47 GP/s</strong></li></ul><p>Sur <strong>C2070</strong>, nos d&#xE9;bits sont de <strong>1666 MP/S</strong> et <strong>5280 MP/s</strong>. Les d&#xE9;bits maximum atteignent <strong>2140 MP/s</strong> et <strong>8540 MP/s</strong> (4090x4096, masque 3x3)</p></div><div class="step" step="47" data-x="75200" data-y="0"><h1 id="id64">LE FILTRAGE DES IMAGES</h1><h2 id="id65">Les filtres de convolution GPU</h2><p>Convolution <strong>s&#xE9;parable</strong> sur C2070.</p><p>Impl&#xE9;mentation Nvidia (m&#xE9;moire partag&#xE9;e)</p><blockquote><ul><li>D&#xE9;bit global max : <strong>1933 MP/s</strong>.</li><li>D&#xE9;bit de calcul max : <strong>6000 MP/s</strong></li></ul></blockquote><p>Notre impl&#xE9;mentation</p><blockquote><ul><li>Optimum &#xE0; 8 pixels par thread.</li><li>Une convolution 1D en m&#xE9;moire partag&#xE9;e, l'autre en registres. Copie interm&#xE9;diaire en m&#xE9;moire globale (cache 1D rapide).</li><li>D&#xE9;bit global : <strong>2028 MP/s</strong>.</li><li>D&#xE9;bit de calcul : <strong>7626 MP/s</strong></li><li>Le gain est obtenu sur la convolution 1D en registres.</li></ul></blockquote></div><div class="step" step="48" data-x="76800" data-y="0"><h1 id="id66">LE FILTRAGE DES IMAGES</h1><h2 id="id67">Les filtres de convolution GPU</h2><p><strong>Conclusion</strong></p><blockquote><ul><li>Am&#xE9;lioration limit&#xE9;e des d&#xE9;bits globaux en raison de la pr&#xE9;pond&#xE9;rance des temps de transfert.</li><li>Am&#xE9;lioration sensible sur les d&#xE9;bits de calcul (de 17 &#xE0; 33 %).</li><li>Le traitement 1D est jusqu'&#xE0; 66% plus rapide. Applicable &#xE0; d'autres signaux 1D.</li></ul></blockquote></div><div class="step" step="49" data-x="78400" data-y="0"><h1 id="id68">LE FILTRAGE DES IMAGES</h1><h2 id="filtre-par-recherche-des-lignes-de-niveaux">Filtre par recherche des lignes de niveaux</h2></div><div class="step" step="50" data-x="80000" data-y="0"><h1 id="id69">LE FILTRAGE DES IMAGES</h1><h2 id="id70">Filtre par recherche des lignes de niveaux</h2><p><strong>Motivations :</strong></p><blockquote><ul><li>Les algorithmes qui d&#xE9;bruitent le mieux sont lents (BM3D).</li><li>Les images naturelles sont d&#xE9;composables en un ensemble de lignes de niveaux ( iso-niveau de gris ).</li><li>Concevoir un algorithme GPU original et son impl&#xE9;mentation.</li></ul></blockquote></div><div class="step" step="51" data-x="81600" data-y="0"><h1 id="id71">LE FILTRAGE DES IMAGES</h1><h2 id="id72">Filtre par recherche des lignes de niveaux</h2><p><strong>Principe - mod&#xE8;le</strong></p><blockquote><ul><li>Estimation locale, par maximum de vraisemblance, des lignes de niveaux.</li><li>R&#xE9;duction de bruit par moyennage le long de la ligne estim&#xE9;e.</li><li>Les lignes de niveaux estim&#xE9;es sont mod&#xE9;lis&#xE9;es par des lignes bris&#xE9;es nomm&#xE9;es <strong>isolines</strong>.</li><li>Les segments des lignes bris&#xE9;es sont choisis parmi des motifs pr&#xE9;-&#xE9;tablis (32 motifs).<img src="img/P5Q1.png" alt="" width="500px" height=""></img></li></ul></blockquote></div><div class="step" step="52" data-x="83200" data-y="0"><h1 id="id73">LE FILTRAGE DES IMAGES</h1><h2 id="id74">Filtre par recherche des lignes de niveaux</h2><p><strong>Principe (&#xE9;tape 1)</strong></p><blockquote><ul><li>En chaque pixel, recherche du motif maximisant la log-vraisemblance ( \(n=6, \sigma^2 =\) variance )</li></ul>$$-\frac{n}{2}log\left(2\pi\right) - \frac{n}{2}log\left(\sigma^2\right) - \frac{n}{2}$$<ul><li>M&#xE9;morisation des param&#xE8;tres des motifs s&#xE9;lectionn&#xE9;s dans deux matrices \(I_{\Theta}\) et \(I_{\Sigma}\).</li></ul><img src="img/lniv-mv.png" alt="" width="500px" height=""></img></blockquote></div><div class="step" step="53" data-x="84800" data-y="0"><h1 id="id75">LE FILTRAGE DES IMAGES</h1><h2 id="id76">Filtre par recherche des lignes de niveaux</h2><p><strong>Principe (&#xE9;tape 2)</strong></p><blockquote><ul><li>Allongement it&#xE9;ratif des segments sous condition GLRT.</li></ul>$$(n_{s_1s_2}+n_{s_3})\left[log\left(\widehat{\sigma_{s_1s_2}}^2\right) - log\left(\widehat{\sigma_{s_3}}^2\right) \right]$$<img src="img/pipd-detail.png" alt="" width="900px" height=""></img></blockquote></div><div class="step" step="54" data-x="86400" data-y="0"><h1 id="id77">LE FILTRAGE DES IMAGES</h1><h2 id="id78">Filtre par recherche des lignes de niveaux</h2><p><strong>Principe (&#xE9;tape 3)</strong></p><blockquote><p>Compensation de la non robustesse de s&#xE9;lection des motifs dans les zones homog&#xE8;nes.</p><blockquote><ul><li>identification des zones homog&#xE8;nes avec un d&#xE9;tecteur de bords.</li><li>Application d'un filtre moyenneur dans ces zones.</li></ul></blockquote><img src="img/detecteur.png" alt="" width="400px" height=""></img></blockquote><div class="notes"><ul><li>Sous-ensembles de pixels n'ayant pas d'intersection --&gt; MV</li><li>Utilisation des motifs des segments pour gain de temps.</li></ul></div></div><div class="step" step="55" data-x="88000" data-y="0"><h1 id="id79">LE FILTRAGE DES IMAGES</h1><h2 id="id80">Filtre par recherche des lignes de niveaux</h2><p><strong>R&#xE9;sultats</strong></p><blockquote><p>Sur l'ensemble d'images de S. Lansel (DenoiseLab, Universit&#xE9; Stanford), filtre propos&#xE9; (PI-PD)</p><ul><li>Am&#xE9;lioration moyenne du rapport Signal sur bruit: <strong>+7,1 dB</strong></li><li>Indice de similarit&#xE9; structurelle : <strong>+30%</strong></li><li>Temps de calcul : <strong>7 ms</strong></li></ul><p>Comparaison avec BM3D</p><ul><li>Am&#xE9;lioration moyenne du rapport Signal sur bruit: <strong>+9,5 dB</strong></li><li>Indice de similarit&#xE9; structurelle : <strong>+36%</strong></li><li>Temps de calcul : <strong>4300 ms</strong></li></ul></blockquote></div><div class="step" step="56" data-x="89600" data-y="0"><h1 id="id81">LE FILTRAGE DES IMAGES</h1><h2 id="id82">Filtre par recherche des lignes de niveaux</h2><table cellpadding="0" cellspacing="0"><tbody><tr><td><img src="img/zoom_noisy.png" alt="" width="" height=""></img></td><td></td><td><img src="img/zoom_mean5.png" alt="" width="" height=""></img></td></tr><tr><td><p>Bruit gaussien \(\sigma=25\)</p></td><td></td><td><p>Moyennage 5x5</p></td></tr><tr><td><img src="img/zoom_pipdh.png" alt="" width="" height=""></img></td><td></td><td><img src="img/zoom_bm3d.png" alt="" width="" height=""></img></td></tr><tr><td><p>PI-PD</p></td><td></td><td><p>BM3D</p></td></tr></tbody></table></div><div class="step" step="57" data-x="91200" data-y="0"><h1 id="id83">LE FILTRAGE DES IMAGES</h1><h2 id="id84">Filtre par recherche des lignes de niveaux</h2><p><strong>Synth&#xE8;se - conclusion</strong></p><blockquote><ul><li>Rapport qualit&#xE9;/temps &#xE9;lev&#xE9;.</li><li>Traitement d'images HD &#xE0; 20 fps.</li><li>Artefacts en marche d'escalier. R&#xE9;duits par la m&#xE9;thode de Buades <em>et al.</em> (+1 dB, +0,2 ms pour 512x512).</li><li>Extension aux images couleurs et autres types de bruits (multiplicatif).</li><li>Algorithme original sans impl&#xE9;mentation s&#xE9;quentielle de r&#xE9;f&#xE9;rence.</li></ul></blockquote></div><div class="step" step="58" data-x="92800" data-y="0"><h1 id="conclusion-generale-perspectives">CONCLUSION G&#xC9;N&#xC9;RALE - PERSPECTIVES</h1><ul><li>Trois types de conception mis en &#x153;uvre.</li><li>Le portage efficace d'algorithme peut s'av&#xE9;rer tr&#xE8;s complexe, voire sans int&#xE9;r&#xEA;t.</li><li>L'emploi de la m&#xE9;moire partag&#xE9;e n'apporte pas les meilleures performances en cas de recouvrements.</li><li>Filtres utilisables par tout programmeur gr&#xE2;ce &#xE0; un g&#xE9;n&#xE9;rateur de code.</li><li>Beaucoup de traitements et domaines peuvent b&#xE9;n&#xE9;ficier des techniques propos&#xE9;es.</li><li>Les &#xE9;volutions de l'architecture laissent entrevoir de nouvelles possibilit&#xE9;s.</li></ul><div class="notes"><ul><li>certaines ardeurs ont &#xE9;t&#xE9; refroidies</li></ul></div></div></div><div id="hovercraft-help"><table><tr><th>Space</th><td>Forward</td></tr><tr><th>Left, Down, Page Down</th><td>Next slide</td></tr><tr><th>Right, Up, Page Up</th><td>Previous slide</td></tr><tr><th>P</th><td>Open presenter console</td></tr><tr><th>H</th><td>Toggle this help</td></tr></table></div><script type="text/javascript" src="js/impress.js"></script><script type="text/javascript" src="js/impressConsole.js"></script><script type="text/javascript" src="js/hovercraft.js"></script></body></html>