<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>Artisan Numérique</title>
  <link rel="alternate" type="text/html" href="http://artisan.karma-lab.net/node/1521"/>
  <link rel="self" type="application/atom+xml" href="http://artisan.karma-lab.net/node/1521/atom/feed"/>
  <id>http://artisan.karma-lab.net/node/1521/atom/feed</id>
  <updated>2008-05-22T19:30:31+02:00</updated>
  <entry>
    <title>PovRay et multi-coeurs</title>
    <link rel="alternate" type="text/html" href="http://artisan.karma-lab.net/node/1521" />
    <id>http://artisan.karma-lab.net/node/1521</id>
    <published>2008-04-03T19:40:50+02:00</published>
    <updated>2008-05-22T19:30:31+02:00</updated>
    <author>
      <name>Ulhume</name>
    </author>
    <category term="3D" />
    <category term="OK" />
    <category term="Planet Libre" />
    <category term="Tutoriel" />
    <summary type="html"><![CDATA[<p>
  Officiellement POVRay devrait dans sa version 3.7 gérer le rendu sur plusieurs coeurs simultanément. La <a class='external' target='_blank' href='http://www.povray.org/beta/' >béta</a> le fait déjà officiellement mais elle plante chez moi. De plus <a class='external' target='_blank' href='http://megapov.inetart.net/' >megapov</a> étant un must, il faudra aussi attendre que cette version soit mis à jour. Entre temps, voici donc une astuce pour profiter de tout ces processeurs qui roupillent.
</p>
    ]]></summary>
    <content type="html"><![CDATA[<p>
  Officiellement POVRay devrait dans sa version 3.7 gérer le rendu sur plusieurs coeurs simultanément. La <a class='external' target='_blank' href='http://www.povray.org/beta/' >béta</a> le fait déjà officiellement mais elle plante chez moi. De plus <a class='external' target='_blank' href='http://megapov.inetart.net/' >megapov</a> étant un must, il faudra aussi attendre que cette version soit mis à jour. Entre temps, voici donc une astuce pour profiter de tout ces processeurs qui roupillent.
</p>
<!--break-->

	<a name='chapter_1'></a>
  <h2>Profiter de l'illumination partielle</h2>
	
<p>
   POVRay permet depuis toujours d'illuminer une zone seulement de l'image finale. Cette zone peut être définie d'une ligne à une autre et/ou d'une colonne à une autre. L'avantage de cette possibilité est que le temps pour illuminer une zone seulement de l'image finale est évidemment moins important qu'illuminer la scène complète, et c'est bien cela qui va nous aider. 
</p>
<p>
  Imaginons que nous ayons deux coeurs à disposition pour une image de 800 lignes, l'astuce consiste donc simplement à lancer deux sessions de povray en parallèle, l'une illuminant les lignes de 1 à 400, l'autre de 401 à 800. C'est aussi bête que cela :

  <div class='code-block code-block-fragment'>
  <div class='container'>
  povray ma_scene.ini +sr <span class="nu0">1</span> +er <span class="nu0">400</span> -Orendu_1.ppm <span class="sy0">&amp;</span><br />
povray ma_scene.ini +sr <span class="nu0">401</span> +er <span class="nu0">400</span> -Orendu_2.ppm <span class="sy0">&amp;</span>
  </div>
  
  </div>
</p>
<p>
  Alors pour être honnête, ce n'est pas aussi bien que lorsque povray supportera réellement le multi-coeurs car les deux sessions sont obligées de perdre le même temps à analyser la scène. Du coup dans notre cas, plus l'image finale est grande, plus le gain est important. 
</p>


	<a name='chapter_2'></a>
  <h2>Recoller les morceaux</h2>
	
<p>
  Une fois le rendu terminé, nous avons deux images au format PPM qui chacune comporte une tranche de l'image finale. Le format PPM est ici choisi pour la simplicité car le jeu va maintenant consister à faire coïncider ces deux tranches pour former l'image finale. C'est ce que fait le code java suivant (codé très rapidement, donc soyez indulgent <img src="http://artisan.karma-lab.net/sites/all/modules/contrib/smileys/packs/crystal/smile.gif" title="Smiling" alt="Smiling" class="smiley-content"/> )

  <div class='code-block code-block-fragment'>
  <div class='container'>
  <span class="kw1">public</span> <span class="kw1">class</span> CombinePPM <span class="br0">&#123;</span><br />
&nbsp; <span class="kw1">public</span> <span class="kw1">static</span> <a target="blank" href="http://www.google.com/search?hl=en&amp;q=allinurl%3AString+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span class="kw3">String</span></a> readTag<span class="br0">&#40;</span><a target="blank" href="http://www.google.com/search?hl=en&amp;q=allinurl%3AInputStream+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span class="kw3">InputStream</span></a> stream<span class="br0">&#41;</span> <span class="kw1">throws</span> <a target="blank" href="http://www.google.com/search?hl=en&amp;q=allinurl%3AIOException+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span class="kw3">IOException</span></a> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; <span class="kw4">int</span> data<span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; <a target="blank" href="http://www.google.com/search?hl=en&amp;q=allinurl%3AString+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span class="kw3">String</span></a> result <span class="sy0">=</span> <span class="st0">&quot;&quot;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; <span class="kw1">while</span> <span class="br0">&#40;</span><span class="br0">&#40;</span>data <span class="sy0">=</span> stream.<span class="me1">read</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="sy0">!=</span> <span class="nu0">-1</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>data <span class="sy0">==</span> <span class="st0">'<span class="es0">\t</span>'</span> <span class="sy0">||</span> data <span class="sy0">==</span> <span class="st0">'<span class="es0">\n</span>'</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">break</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; result <span class="sy0">+=</span> <span class="br0">&#40;</span><span class="kw4">char</span><span class="br0">&#41;</span> data<span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; &nbsp; <span class="kw1">return</span> result<span class="sy0">;</span><br />
&nbsp; <span class="br0">&#125;</span><br />
<br />
&nbsp;<span class="kw1">public</span> <span class="kw1">static</span> <span class="kw4">void</span> combine<span class="br0">&#40;</span><a target="blank" href="http://www.google.com/search?hl=en&amp;q=allinurl%3AString+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span class="kw3">String</span></a> source<span class="br0">&#41;</span> <span class="kw1">throws</span> <a target="blank" href="http://www.google.com/search?hl=en&amp;q=allinurl%3AIOException+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span class="kw3">IOException</span></a> <span class="br0">&#123;</span><br />
<br />
&nbsp; &nbsp; &nbsp; <span class="kw4">int</span> bits<span class="sy0">;</span> <span class="kw4">int</span> width <span class="sy0">=</span> <span class="nu0">0</span><span class="sy0">;</span> <span class="kw4">int</span> height <span class="sy0">=</span> <span class="nu0">0</span><span class="sy0">;</span><br />
<br />
&nbsp; &nbsp; &nbsp; <a target="blank" href="http://www.google.com/search?hl=en&amp;q=allinurl%3AFileOutputStream+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span class="kw3">FileOutputStream</span></a> fileOutputStream <span class="sy0">=</span> <span class="kw1">new</span> <a target="blank" href="http://www.google.com/search?hl=en&amp;q=allinurl%3AFileOutputStream+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span class="kw3">FileOutputStream</span></a><span class="br0">&#40;</span><span class="kw1">new</span> <a target="blank" href="http://www.google.com/search?hl=en&amp;q=allinurl%3AFile+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span class="kw3">File</span></a><span class="br0">&#40;</span>outputFile, source <span class="sy0">+</span> <span class="st0">&quot;.ppm&quot;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; <span class="kw4">int</span> offset <span class="sy0">=</span> <span class="nu0">0</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; <span class="kw1">for</span> <span class="br0">&#40;</span><span class="kw4">int</span> counter <span class="sy0">=</span> <span class="nu0">1</span><span class="sy0">;;</span> counter<span class="sy0">++</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <a target="blank" href="http://www.google.com/search?hl=en&amp;q=allinurl%3AFile+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span class="kw3">File</span></a> file <span class="sy0">=</span> <span class="kw1">new</span> <a target="blank" href="http://www.google.com/search?hl=en&amp;q=allinurl%3AFile+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span class="kw3">File</span></a><span class="br0">&#40;</span>outputFile, source <span class="sy0">+</span> <span class="st0">&quot;_&quot;</span> <span class="sy0">+</span> counter <span class="sy0">+</span> <span class="st0">&quot;.ppm&quot;</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="sy0">!</span>file.<span class="me1">exists</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>counter <span class="sy0">==</span> <span class="nu0">1</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">throw</span> <span class="kw1">new</span> <a target="blank" href="http://www.google.com/search?hl=en&amp;q=allinurl%3ARuntimeException+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span class="kw3">RuntimeException</span></a><span class="br0">&#40;</span><span class="st0">&quot;Unable to find any data&quot;</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">break</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <a target="blank" href="http://www.google.com/search?hl=en&amp;q=allinurl%3AFileInputStream+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span class="kw3">FileInputStream</span></a> stream <span class="sy0">=</span> <span class="kw1">new</span> <a target="blank" href="http://www.google.com/search?hl=en&amp;q=allinurl%3AFileInputStream+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span class="kw3">FileInputStream</span></a><span class="br0">&#40;</span>file<span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <a target="blank" href="http://www.google.com/search?hl=en&amp;q=allinurl%3AString+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span class="kw3">String</span></a> header <span class="sy0">=</span> readTag<span class="br0">&#40;</span>stream<span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <a target="blank" href="http://www.google.com/search?hl=en&amp;q=allinurl%3AString+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span class="kw3">String</span></a> sizeTag <span class="sy0">=</span> readTag<span class="br0">&#40;</span>stream<span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <a target="blank" href="http://www.google.com/search?hl=en&amp;q=allinurl%3AString+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span class="kw3">String</span></a> bitsTag <span class="sy0">=</span> readTag<span class="br0">&#40;</span>stream<span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="sy0">!</span>header.<span class="me1">equals</span><span class="br0">&#40;</span><span class="st0">&quot;P6&quot;</span><span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">throw</span> <span class="kw1">new</span> <a target="blank" href="http://www.google.com/search?hl=en&amp;q=allinurl%3ARuntimeException+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span class="kw3">RuntimeException</span></a><span class="br0">&#40;</span><span class="st0">&quot;Wrong file format for &quot;</span> <span class="sy0">+</span> file <span class="sy0">+</span> <span class="st0">&quot;, only raw PPN accepted.&quot;</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>counter <span class="sy0">==</span> <span class="nu0">1</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <a target="blank" href="http://www.google.com/search?hl=en&amp;q=allinurl%3AString+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span class="kw3">String</span></a><span class="br0">&#91;</span><span class="br0">&#93;</span> size <span class="sy0">=</span> sizeTag.<span class="me1">split</span><span class="br0">&#40;</span><span class="st0">&quot;<span class="es0">\\</span>s&quot;</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; width <span class="sy0">=</span> <a target="blank" href="http://www.google.com/search?hl=en&amp;q=allinurl%3AInteger+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span class="kw3">Integer</span></a>.<span class="me1">parseInt</span><span class="br0">&#40;</span>size<span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; height <span class="sy0">=</span> <a target="blank" href="http://www.google.com/search?hl=en&amp;q=allinurl%3AInteger+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span class="kw3">Integer</span></a>.<span class="me1">parseInt</span><span class="br0">&#40;</span>size<span class="br0">&#91;</span><span class="nu0">1</span><span class="br0">&#93;</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; bits <span class="sy0">=</span> <a target="blank" href="http://www.google.com/search?hl=en&amp;q=allinurl%3AInteger+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span class="kw3">Integer</span></a>.<span class="me1">parseInt</span><span class="br0">&#40;</span>bitsTag<span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; fileOutputStream.<span class="me1">write</span><span class="br0">&#40;</span><span class="br0">&#40;</span><span class="st0">&quot;P6<span class="es0">\n</span>&quot;</span> <span class="sy0">+</span> size<span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span> <span class="sy0">+</span> <span class="st0">&quot; &quot;</span> <span class="sy0">+</span> size<span class="br0">&#91;</span><span class="nu0">1</span><span class="br0">&#93;</span> <span class="sy0">+</span> <span class="st0">&quot;<span class="es0">\n</span>&quot;</span> <span class="sy0">+</span> bits <span class="sy0">+</span> <span class="st0">&quot;<span class="es0">\n</span>&quot;</span><span class="br0">&#41;</span>.<span class="me1">getBytes</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">byte</span><span class="br0">&#91;</span><span class="br0">&#93;</span> rgb <span class="sy0">=</span> <span class="kw1">new</span> <span class="kw4">byte</span><span class="br0">&#91;</span><span class="nu0">3</span><span class="br0">&#93;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">while</span> <span class="br0">&#40;</span>stream.<span class="me1">read</span><span class="br0">&#40;</span>rgb<span class="br0">&#41;</span> <span class="sy0">!=</span> <span class="nu0">-1</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; fileOutputStream.<span class="me1">write</span><span class="br0">&#40;</span>rgb<span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; offset<span class="sy0">++;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; stream.<span class="me1">close</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
<br />
&nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; &nbsp; fileOutputStream.<span class="me1">close</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; <span class="br0">&#125;</span><br />
&nbsp; <span class="kw1">public</span> <span class="kw1">static</span> <span class="kw4">void</span> main<span class="br0">&#40;</span><a target="blank" href="http://www.google.com/search?hl=en&amp;q=allinurl%3AString+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span class="kw3">String</span></a><span class="br0">&#91;</span><span class="br0">&#93;</span> args<span class="br0">&#41;</span> <span class="kw1">throws</span> <a target="blank" href="http://www.google.com/search?hl=en&amp;q=allinurl%3AIOException+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span class="kw3">IOException</span></a> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; combine<span class="br0">&#40;</span>args<span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; <span class="br0">&#125;</span><br />
<span class="br0">&#125;</span>
  </div>
  <div class='caption'>fichier combineppm.java</div>
  </div>
</p>
<p>
  Maintenant pour l'utiliser sur notre précédent résultat :
  
  <div class='code-block code-block-fragment'>
  <div class='container'>
  javac combineppm.java<br />
java -cp . CombinePPM result
  </div>
  
  </div>
</p>

	<a name='chapter_3'></a>
  <h2>La même chose, à distance</h2>
	
<p>
  Et voilà, le tout collé dans un petit script et vous divisez le temps de rendu par autant de coeurs disponibles. Maintenant il est possible par ssh de faire la même chose mais à distance cette fois :
  
  <div class='code-block code-block-fragment'>
  <div class='container'>
  <a target="blank" href="http://pwet.fr/man/linux/commandes/ssh"><span class="kw2">ssh</span></a> machine_de_guerre <span class="st0">&quot;povray ma_scene.ini +sr 1 +er 400 -Orendu_1.ppm ; cat rendu_1.ppm&quot;</span> <span class="sy0">&gt;</span> rendu_1.ppm <span class="sy0">&amp;</span>
  </div>
  
  </div>
</p>

	<a name='chapter_4'></a>
  <h2>Conclusion</h2>
	
<p>
  Voilà, l'avantage est que cela fonctionne tout de suite et avec toutes les versions dérivées de povray. Pour ceux que cela intéresse, j'ai une version plus complète du code java sous la forme d'un petit visualisateur de vue qui découpe et parallélise le rendu et reconstruit l'image finale tout seul en fonction du nombre de coeurs disponible. 
</p>    ]]></content>
  </entry>
</feed>
