Connexion utilisateur
Sommaire
Commentaires récents
 
PovRay et multi-coeurs
Le 3 avril 2008, à 19:40 par Ulhume...

Officiellement POVRay devrait dans sa version 3.7 gérer le rendu sur plusieurs coeurs simultanément. La béta le fait déjà officiellement mais elle plante chez moi. De plus megapov é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.

Profiter de l'illumination partielle

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.

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 :

  1. povray ma_scene.ini +sr 1 +er 400 -Orendu_1.ppm &
  2. povray ma_scene.ini +sr 401 +er 400 -Orendu_2.ppm &

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.

Recoller les morceaux

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 Smiling )

fichier combineppm.java
  1. public class CombinePPM {
  2.   public static String readTag(InputStream stream) throws IOException {
  3.       int data;
  4.       String result = "";
  5.       while ((data = stream.read()) != -1) {
  6.           if (data == '\t' || data == '\n') {
  7.               break;
  8.           }
  9.           result += (char) data;
  10.       }
  11.       return result;
  12.   }
  13.  
  14.  public static void combine(String source) throws IOException {
  15.  
  16.       int bits; int width = 0; int height = 0;
  17.  
  18.       FileOutputStream fileOutputStream = new FileOutputStream(new File(outputFile, source + ".ppm"));
  19.       int offset = 0;
  20.       for (int counter = 1;; counter++) {
  21.           File file = new File(outputFile, source + "_" + counter + ".ppm");
  22.           if (!file.exists()) {
  23.               if (counter == 1) {
  24.                   throw new RuntimeException("Unable to find any data");
  25.               }
  26.               break;
  27.           }
  28.           FileInputStream stream = new FileInputStream(file);
  29.           String header = readTag(stream);
  30.           String sizeTag = readTag(stream);
  31.           String bitsTag = readTag(stream);
  32.           if (!header.equals("P6")) {
  33.               throw new RuntimeException("Wrong file format for " + file + ", only raw PPN accepted.");
  34.           }
  35.           if (counter == 1) {
  36.               String[] size = sizeTag.split("\\s");
  37.               width = Integer.parseInt(size[0]);
  38.               height = Integer.parseInt(size[1]);
  39.               bits = Integer.parseInt(bitsTag);
  40.               fileOutputStream.write(("P6\n" + size[0] + " " + size[1] + "\n" + bits + "\n").getBytes());
  41.           }
  42.           byte[] rgb = new byte[3];
  43.           while (stream.read(rgb) != -1) {
  44.               fileOutputStream.write(rgb);
  45.               offset++;
  46.           }
  47.           stream.close();
  48.  
  49.       }
  50.       fileOutputStream.close();
  51.   }
  52.   public static void main(String[] args) throws IOException {
  53.       combine(args[0]);
  54.   }
  55. }

Maintenant pour l'utiliser sur notre précédent résultat :

  1. javac combineppm.java
  2. java -cp . CombinePPM result

La même chose, à distance

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 :

ssh machine_de_guerre "povray ma_scene.ini +sr 1 +er 400 -Orendu_1.ppm ; cat rendu_1.ppm" > rendu_1.ppm &

Conclusion

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.

Commentaires

malic , le 4 April, 2008 - 09:35

hmmm... Povray, des souvenirs... des casse-tête à l'époque de mon premier PC, où le rendu d'une scène "designed by vi" prenait 1 semaine au grand dame de ma mère qui voyait l'ordi allumé 24h/24.

Merci à un ami photographe de m'avoir récupéré un coprocesseur arithmétique Smiling ça a changé ma vie... (pas vraiment celle de ma mère car les scènes ont fait un bond en complexité pour rester à 1 semaine de rendu)

Pour en revenir au multi-coeur, j'avais bidouillé un programme avec PVM à la fac pour faire le rendu d'une scène sur un parc de machines en divisant la scène sur le même principe.

Ca fait longtemps que je n'ai pas regarder POV mais avec la prise en main des modeleurs surfaciques (3DS Max et consors), j'ai perdu l'habitude de concevoir une scène sur un mode volumique et POV était très mal adapté au modèle à base de surfaces. Tiens, je vais installer Blender histoire de me faire la main dessus pour voir où on en est, pour le modelage et le reste.

Ulhume, le 4 April, 2008 - 17:57

@malic
Je sais bien, je crois que les premiers souvenirs et que j'ai de Linux et de PovRay, viennent de toi Wink

Pour le rendu surfacique et POV, ça a le mérite d'être clair. En revanche pour faire de l'architectural, la raison pour laquelle je l'utilise en ce moment, cela reste à mon sens beaucoup plus pratique que Blender. Ne serais-ce que par l'approche script qui permet de monter rapidement des murs, portes, fenêtres, etc avec des dimensions réelles. Peut-être la même chose est-elle faisable avec Blender via python mais je n'ai pas eu le temps/courage de me pencher là dessus.

Maintenant POV me semble aller doucement vers sa belle mort, le gens semble avoir désertés et les sites qui en parlent font très web 1.0 Wink

Poster un nouveau commentaire

Le contenu de ce champ est gardé secret et ne sera pas montré publiquement.
  • Allowed HTML tags: <a> <em> <strong> <cite> <code> <ul> <ol> <li> <dl> <dt> <dd>
  • To highlight piece of code, just surround them with <code type="language"> Your code &tl;/code>>. Language can be java,c++,bash,etc... Everything Geshi support.
  • Les lignes et les paragraphes vont à la ligne automatiquement.
  • Textual smileys will be replaced with graphical ones.
  • Les adresses de pages web et de messagerie électronique sont transformées en liens automatiquement.

Plus d'informations sur les options de formatage