Walt Disney Animation Studios (WDAS) a récemment fait un cadeau inestimable à la communauté de la recherche sur le rendu en libérant une
scène d'île complète du dessin animé Moana . La géométrie et les textures d'une image occupent plus de 70 Go d'espace disque. C'est un formidable exemple du degré de complexité auquel les systèmes de rendu doivent faire face aujourd'hui; Jamais auparavant les chercheurs et développeurs impliqués dans le rendu en dehors des studios de cinéma n'ont pu travailler avec des scènes aussi réalistes.
Voici à quoi ressemble le résultat du rendu d'une scène avec pbrt moderne:
Une île de Moana rendue par pbrt-v3 à une résolution de 2048x858 avec 256 échantillons par pixel. Le temps de rendu total sur une instance 12 cœurs / 24 threads de Google Compute Engine avec une fréquence de 2 GHz avec la dernière version de pbrt-v3 était de 1 h 44 min 45 s.De la part de Disney, c'était un travail énorme, elle a dû extraire la scène de son propre format interne et la convertir au format habituel; Un grand merci à elle pour le temps consacré à l'emballage et à la préparation de ces données pour une utilisation généralisée. Je suis sûr que leur travail sera bien récompensé à l'avenir car les chercheurs utilisent cette scène pour étudier les problèmes de rendu efficace de scènes de ce niveau de complexité.
Cette scène m'a déjà beaucoup appris et m'a permis d'améliorer le rendu pbrt, mais avant de commencer, je vais raconter une courte histoire pour comprendre le contexte.
Le hachage qui n'était pas
Il y a de nombreuses années, lors d'un stage dans l'équipe de rendu Pixar, j'ai appris une curieuse leçon: des choses «intéressantes» apparaissent presque toujours lorsque les données d'entrée sont transmises au système de programme, ce qui est sensiblement différent de tout ce qui était auparavant. Même dans des systèmes logiciels bien écrits et matures, de nouveaux types d'entrée conduisent presque toujours à la découverte de défauts inconnus dans une implémentation existante.
J'ai d'abord appris cette leçon lors de la production de
Toy Story 2 . Un jour, quelqu'un a remarqué qu'un temps incroyable a été consacré à l'analyse des fichiers de description de scène RIB. Quelqu'un d'autre de l'équipe de rendu (je suppose que c'était Craig Kolb) a lancé le profileur et a commencé à le comprendre.
Il s'est avéré que la majeure partie du temps d'analyse était occupée par des recherches dans la table de hachage utilisée pour l'
internement de chaînes . La table de hachage était plutôt petite, probablement 256 éléments, et lorsque plusieurs valeurs étaient hachées dans une cellule, elle organisait une chaîne. Après la première implémentation de la table de hachage, beaucoup de temps s'est écoulé et il y avait maintenant des dizaines de milliers d'objets dans les scènes, donc une si petite table s'est rapidement remplie et est devenue inefficace.
Il était très conseillé d'augmenter simplement la taille de la table - tout cela s'est produit à la hauteur du flux de travail, donc il n'y avait pas de temps pour une sorte de solution élégante, par exemple, augmenter la taille de la table lors du remplissage. Nous effectuons un changement sur une seule ligne, reconstruisons l'application, effectuons un test rapide avant de valider et ... aucune amélioration de la vitesse ne se produit. La recherche d'une table de hachage prend le même temps. Génial!
Après une étude plus approfondie, nous avons constaté que la fonction de table de hachage utilisée était similaire à la suivante:
int hash(const char *str) { return str[0]; }
(Pardonnez-moi, Pixar, si je révèle votre code source RenderMan top secret.)
La fonction de «hachage» a été mise en œuvre dans les années 80. À ce moment-là, le programmeur a probablement considéré que le coût de calcul de la vérification de l'effet de tous les caractères de la chaîne sur la valeur de hachage serait trop élevé et n'en valait pas la peine. (Je pense que s'il n'y avait que quelques objets et 256 éléments dans la table de hachage de la scène, cela suffisait.)
Une autre implémentation obsolète a contribué: à partir du moment où Pixar a commencé à créer ses films, les noms des objets dans les scènes ont beaucoup augmenté, par exemple, «BuzzLightyear / LeftArm / Hand / IndexFinger / Knuckle2». Cependant, une étape initiale du pipeline a utilisé un tampon de longueur fixe pour stocker les noms des objets et raccourci tous les noms longs, en ne conservant que la fin, et avec de la chance, a ajouté des points de suspension au début, indiquant clairement qu'une partie du nom a été perdue: "... year / LeftArm / Hand / IndexFinger / Knuckle2 ".
Par la suite, tous les noms des objets que le moteur de rendu a vu avaient cette forme, la fonction de hachage les a tous hachés dans une seule pièce de mémoire en tant que «.», Et la table de hachage était en fait une grande liste chaînée. Bon vieux temps. Au moins, après l'avoir compris, nous avons rapidement corrigé cette erreur.
Une innovation intrigante
Cette leçon m'a été rappelée l'année dernière lorsque Heather Pritchet et Rasmus Tamstorf de WDAS m'ont contacté et m'ont demandé si je serais intéressé à vérifier la qualité possible du rendu de la scène de
Moana en
pbrt 1 . Naturellement, j'ai accepté. J'étais heureux d'aider et je me demandais comment tout se passerait.
L'optimiste naïf en moi espérait qu'il n'y aurait pas de grandes surprises - au final, la première version de pbrt est sortie il y a environ 15 ans, et beaucoup de gens ont utilisé et étudié son code pendant de nombreuses années. Vous pouvez être sûr qu'il n'y aura pas d'interférence comme l'ancienne fonction de hachage de RenderMan, non?
Bien sûr, la réponse était non. (Et c'est pourquoi j'écris ceci et quelques autres articles.) Bien que j'étais un peu déçu que pbrt n'ait pas été parfait "prêt à l'emploi", mais je pense que mon expérience avec la scène
Moana a été la première confirmation de la valeur de la publication de cette scène ; pbrt est déjà devenu un meilleur système grâce au fait que j'ai compris comment gérer cette scène.
Premiers rendus
Après avoir accédé à la scène, je l'ai immédiatement téléchargé (cela a pris plusieurs heures avec ma connexion Internet à domicile) et l'ai déballé de tar, recevant 29 Go de fichiers pbrt et 38 Go de cartes de texture
ptex 2 . J'ai essayé allègrement de rendre la scène sur mon système domestique (avec 16 Go de RAM et un processeur à 4 cœurs). Après être retourné à l'ordinateur après un certain temps, j'ai vu qu'il était gelé, toute la RAM était pleine et pbrt essayait toujours de terminer l'analyse de la description de la scène. Le système d'exploitation a cherché à faire face à la tâche en utilisant la mémoire virtuelle, mais cela semblait sans espoir. Ayant battu le processus, j'ai dû attendre encore une minute avant que le système ne commence à réagir à mes actions.
La prochaine tentative était une instance de Google Compute Engine, qui vous permet d'utiliser plus de RAM (120 Go) et plus de CPU (32 threads sur 16 CPU). La bonne nouvelle était que pbrt a réussi à rendre la scène avec succès (grâce au travail de Heather et Rasmus pour la convertir au format pbrt). C'était très excitant de voir que pbrt peut générer des pixels relativement bons pour un contenu de film de haute qualité, mais la vitesse s'est avérée pas si étonnante: 34 min 58 s uniquement pour analyser la description de la scène et pendant le rendu, le système a dépensé jusqu'à 70 Go de RAM.
Oui, il y avait 29 gigaoctets de fichiers de description de scène au format pbrt sur le disque qui devaient être épargnés, donc je ne m'attendais pas à ce que la première étape prenne quelques secondes. Mais passer une demi-heure avant même que les rayons commencent à tracer? Cela complique grandement le travail avec la scène.
D'un autre côté, cette vitesse nous a indiqué que quelque chose de très nauséabond se passait probablement dans le code; pas seulement «l'inversion de matrice peut être effectuée 10% plus rapidement»; plutôt, quelque chose au niveau de "oh, nous parcourons une liste chaînée de 100 mille éléments". J'étais optimiste et j'espérais qu'après l'avoir compris, je pourrais accélérer considérablement le processus.
Les statistiques n'aident pas
Le premier endroit où j'ai commencé à chercher des indices était les statistiques de vidage de pbrt après le rendu. Les principales étapes de l'exécution de pbrt sont configurées de sorte que vous puissiez collecter des données de profilage approximatives en corrigeant les opérations avec des interruptions périodiques pendant le processus de rendu. Malheureusement, les statistiques ne nous ont pas beaucoup aidés: selon les rapports, près de 35 minutes avant le début du rendu, 4 minutes 22 secondes ont été consacrées à la construction du BVH, mais aucun détail n'a été fourni sur le reste du temps.
La construction de BVH est la seule tâche de calcul importante effectuée pendant l'analyse de scène; tout le reste est essentiellement une désérialisation de la géométrie et des descriptions de matériaux. Connaître le temps passé à créer le BVH a permis de comprendre à quel point le système était (peu) efficace: le temps restant, à savoir environ 30 minutes, analysait 29 Go de données, c'est-à-dire que la vitesse était de 16,5 Mo / s. Des analyseurs JSON bien optimisés, effectuant essentiellement la même tâche, fonctionnent à une vitesse de 50-200 Mo / s. De toute évidence, il y a encore place à amélioration.
Pour mieux comprendre le temps perdu, j'ai lancé pbrt avec un outil de
perf Linux que je n'avais jamais utilisé auparavant. Mais, il semble, il a fait face à la tâche. Je lui ai demandé de rechercher des caractères DWARF pour obtenir les noms des fonctions (
--call-graph dwarf
), et pour ne pas obtenir les fichiers de trace de 100 Go, j'ai dû réduire le taux d'échantillonnage de 4000 à 100 échantillons par seconde (
-F 100
). Mais avec ces paramètres, tout s'est bien passé, et j'ai été agréablement surpris que l'outil de
perf report
performance ait une interface avec de belles malédictions.
Voici ce qu'il a pu me dire après avoir commencé avec pbrt:
Je ne plaisantais pas quand je parlais de "l'interface avec de belles malédictions".Nous voyons que plus de la moitié du temps est consacré à l'analyse de la mécanique:
yyparse()
est le
yyparse()
généré par le
bison , et
yylex()
est l'analyseur lexical (lexer) généré par
flex . Plus de la moitié du temps dans
yylex()
est consacré à
strtod()
, qui convertit les chaînes en valeurs doubles. Nous
yyparse()
attaque sur
yyparse()
et
yylex()
jusqu'au troisième article de cette série, mais nous pouvons déjà comprendre que ce pourrait être une bonne idée de réduire la quantité de données jetées dans le moteur de rendu.
Du texte au PLY
Une façon de passer moins de temps à analyser les données de texte consiste à convertir les données dans un format analysé plus efficacement. La plupart des 29 Go de ces fichiers de description de scène sont des maillages triangulaires, et pbrt a déjà un support natif pour
le format PLY , qui est une représentation binaire efficace des maillages polygonaux. Dans pbrt, il existe également un indicateur de ligne de commande
--toply
, qui analyse le fichier de description de scène pbrt, convertit tous les maillages triangulaires trouvés en fichiers PLY et crée un nouveau fichier pbrt qui fait référence à ces fichiers PLY.
Le hic, c'est que les textures
ptex sont activement utilisées dans la scène Disney, qui, à son tour, nécessite qu'une valeur
faceIndex
soit associée à chaque triangle, ce qui détermine de quelle face du sous-maillage d'origine il est tiré. Pour transférer ces valeurs, il suffisait simplement d'
ajouter la prise en charge de nouveaux champs dans le fichier PLY . Des recherches supplémentaires ont révélé que dans le cas de la conversion de chaque maillage - même s'il ne comporte qu'une douzaine de triangles - en un fichier PLY, des dizaines de milliers de petits fichiers PLY sont créés dans le dossier, ce qui crée ses propres problèmes de performances; Nous avons réussi à nous débarrasser de ce problème en ajoutant à l'implémentation la
possibilité de laisser les petites mailles inchangées .
J'ai écrit un
petit script de ligne de commande pour convertir tous les fichiers
*_geometry.pbrt
dans un dossier pour utiliser PLY pour les grands maillages. Notez qu'il contient des hypothèses codées en dur sur les chemins qui doivent être modifiés pour que le script fonctionne ailleurs.
Premier boost de vitesse
Après avoir converti tous les grands maillages en PLY, la taille de la description de scène sur le disque est passée de 29 à 22 Go: 16,9 Go de fichiers de scène pbrt et 5,1 Go de fichiers binaires PLY. Après la conversion, le temps total de la première étape du système a diminué à 27 minutes 35 secondes, et les économies se sont élevées à 7 minutes 23 secondes, c'est-à-dire que nous avons accéléré de 1,3 fois
3 . Le traitement d'un fichier PLY est beaucoup plus efficace que le traitement d'un fichier texte pbrt: seulement 40 secondes de temps de démarrage ont été consacrées à l'analyse des fichiers PLY, et nous constatons que les fichiers PLY ont été traités à une vitesse d'environ 130 Mo / s, soit environ 8 fois plus vite que le format de texte pbrt .
Ce fut une bonne victoire facile, mais nous avions encore beaucoup à faire.
La prochaine fois, nous déterminerons où toute la mémoire est réellement utilisée, corrigons quelques erreurs ici et atteignons encore plus de vitesse dans le processus.
Remarques
- Vous devriez maintenant avoir une meilleure compréhension de la motivation pour ajouter le support ptex de ma part et convertir Disney BSDF en pbrt l'année dernière.
- Tout le temps ici et dans les articles suivants est indiqué pour la version WIP (Work In Progress), avec laquelle j'ai travaillé avant la sortie officielle. Il semble que la version finale soit un peu plus grande. Nous nous en tiendrons aux résultats que j'ai enregistrés en travaillant avec la scène originale, malgré le fait qu'ils ne correspondent pas tout à fait aux résultats de la version finale. Je soupçonne que les leçons à en tirer peuvent être les mêmes.
- Notez que l'augmentation de la vitesse est essentiellement ce à quoi vous vous attendez avec une réduction d'environ 50% du volume des données d'analyse. Le temps que nous passons selon le profileur confirme notre idée.