La ferme de rendu (seconde partie) : Les jobs
Par Narann le samedi, 16 mai 2020, 17:48 - Infographie 3D - Boulot - Lien permanent
Dans la première partie, nous avons abordé les différents jobs qu’on peut retrouver sur une ferme de calcul. Ici nous allons parler de certains aspects tel que la notion de prédiction de données, relation aux versions, gestion du temps de chargement des scènes et des versions des logiciels et plugins.
Prédiction des données
Si vous ne deviez retenir qu’un point de ce billet ce serait celui-là ! :hehe:
Pas forcément connu, ce concept me semble crucial pour gérer les ressources de sa ferme correctement.
Le principe est de savoir exactement quelles données une chaîne de jobs va produire avant de générer les-dites données. Avant de vous expliquer ce que c’est, on va imaginer une gestion de ferme de calcul sans ce principe.
Si vous débutez en gestion de ferme, vous aurez tendance à exécuter des gros scripts qui s’occupent de tout faire à la volée, sans vraiment savoir sur quoi ils vont tomber :
- Ouvrir la scène d’animation Maya.
- Choper des trucs dedans (persos, props, etc.).
- Créer des versions pour les trucs qu’on va exporter en fichiers Alembic.
- Exporter les Alembic.
- Créer des versions pour les trucs qu’on va exporter en fichiers Yeti.
- Exporter les poils Yeti.
Dans le cas de Guerilla :
- Ouvrir le projet Guerilla.
- Choper les trucs dedans (Passe de rendu, AOV, etc.).
- Exporter des RIB.
- Rendre les RIB.
Bim ! Comme ça, d’un coup. :grenadelauncher:
Quand tu as trois personnages légers, c’est cool et plutôt rapide, mais le gros souci de cette méthode c’est que la difficulté à gérer vos jobs augmentera de façon exponentielle au fil de la montée en complexité de vos scènes. Bah oui, si à chaque exécution du job ça recrée des versions, tu vas le sentir passer l’export qui plante et que tu dois relancer dix fois…
Vous l’aurez compris, c’est moisi. Mais qu’est-ce qu’on entend par « gérer vos jobs » ?
Déjà leur utilisation au quotidien : Plus un job est lourd et fait plein de choses, moins il est facile pour les équipes de savoir ce qui est sorti et ce qui ne l’est pas. Sans compter que la moindre chose qui pourrait faire planter le job l’oblige à recommencer entièrement (Et nous savons tous que c’est la dernière partie du job d’export du plan le plus long du projet qui plante, toujours…).
Ensuite le test par les TDs. La facilité à tester un job permet de le développer rapidement (mais ça on s’en fout, parce qu’on sait tous qu’un vrai TD ça fait des cubes et des sphères) et surtout, de le déboguer rapidement moins lentement (Et ça, on s’en fout pas…).
« C’est plus facile de faire un gros script monolithique » diront certains, et ils auront raison, mais je répondrais que « c’est plus facile à déboguer » d’en faire plusieurs petits. Le temps économisé à l’écriture du code se paie par la lourdeur des jobs. En gros, la question n’est pas d’aller vite, mais d’aller loin (C’est beau… :petrus: ).
Le pire, c’est si vos jobs créent des jobs à la volée (création dynamique). Encore une fois, tout ceci est pratique (et parfois nécessaire), mais il n’est pas toujours simple de déboguer de tels jobs.
Je le crie sur tous les toits mais l’argument « c’est plus facile à déboguer » est vraiment fondamental dans un pipeline. En particulier sur les jobs de fermes qu’il est difficile de garder rigides tant ils tendent à évoluer au fil des projets en ouvrant tout et n’importe quoi ; scènes d’animateurs™, scène de rendu, versions des logiciels différentes suivant les projets, etc. Sans compter qu’il faut, pour tester, que la ferme puisse exécuter votre code à vous (La méthode la plus simple consistant à faire passer sa machine pour un worker de la ferme).
Bref, pour pouvoir développer, tester et déboguer des jobs efficacement, il faut qu’ils soient le plus légers et rapide possible (à démarrer et à s’exécuter) et ne fasse qu’une seule et unique chose. La capacité de mettre votre ferme à l’échelle avec des projets de plus en plus gros dépends de ça.
Si vous gardez ça à l’esprit quand vous structurez vos jobs, vous allez vite vous rendre compte que le meilleur (seul ?) moyen d’avoir des jobs précis et granulaires, c’est de savoir à l’avance ce qu’il y a dans vos scènes, c’est-a-dire au moment où vous générez le graphe de dépendance de jobs.
En effet, si vous savez avant d’ouvrir une scène d’animation ce qu’il y a dedans, vous allez pouvoir faire autant de job d’export qu’il y a de personnages (ou prop) et ainsi gagner en temps.
Si vous avez trois personnages avec, pour chaque personnage, un export Alembic et une simulation automatique de cloth, vous aurez une chaîne de six jobs :
toto_001_abc -> toto_001_auto_cloth tata_001_abc -> tata_001_auto_cloth tutu_001_abc -> tutu_001_auto_cloth
Le petit malin du fond me fera remarquer qu’il suffit d’ouvrir la scène Maya et de générer la chaîne de job depuis cette dernière pour savoir ce qu’il y a à générer. Après lui avoir rappelé que les petits malins du fond dans son genre finissent seul, alcoolique et au chômage, je lui expliquerai qu’on a pas que ça à faire d’ouvrir des scènes Maya et que même si on le fait dans un job qui se charge d’ouvrir les scènes Maya pour générer les jobs, on ne sait pas, au moment où on génère ce fameux job ce qu’il va générer. En faisant ça, vous avez simplement décalé le problème. :reflechi:
Bref, pas le choix, il faut connaître à l’avance, au moment où on fait toute la chaîne de job.
Il y a plusieurs méthodes pour y arriver suivant votre pipeline. Voici quelques pistes :
- Écrire un fichier à côté de votre scène (side car) contenant les instances présentes dedans ; toto001, tata001, etc.
- Sauvegarder les informations en métadonnées de votre version dans la base de donnée que vous utilisez.
- Si vous utilisez un pipeline s’appuyant sur des notions de connexions et de nœud, vous pouvez faire un nouveau type de connexion.
- etc.
Ces méthodes ont en commun de s’exécuter au moment de la publication afin d’avoir les informations nécessaires à disposition.
Cela implique aussi que ces informations doivent être accessible et lu au moment de la création du graph de job.
Le versionning
Comme je le disais, un des risques qu’il y a à relancer une chaîne de job non prédictible est de se retrouver avec autant de versions créées que de fois où la chaîne est relancé. Une manière d’éviter ça consiste à créer les versions au moment de la soumission du job. Ceci permet d’avoir une gestion synchrone des versions, mais c’est la ferme, asynchrone par nature, qui va les remplir, puis les « fermer ».
Un problème se pose toutefois rapidement : En effet, quand on crée une version, elle est souvent accessible immédiatement. Ainsi, si vous assemblez un plan dans la minute qui suit la publication d’un asset qui le compose (e.g. l’export d’une animation d’un personnage), le plan assemblé utilisera cette version, mais si la sauvegarde du fichier se fait en décalé (de façon asynchrone, par la ferme), vous risquez d’avoir des problèmes, car l’assembleur de scène ne comprendra pas pourquoi une version existe mais le fichier n’est pas présent et/ou invalide.
Une façon de résoudre ce problème passe par la possibilité d’activer ou de désactiver d’une version. Ainsi, une version crée mais non « fini » (le fichier n’est pas encore là), sera « désactivée » aux yeux du pipeline, et ne sera activé (et ses fichiers mis en lecture seule) qu’une fois la génération du fichier (export Alembic, rendu, playblast, etc.) terminé.
Toute version visant à être « remplis » sur la ferme est donc désactivée à sa création, et un job dédié s’occupe de l’activer quand la chaîne de job est terminé.
Dernier problème (promis) : Si on relance une chaîne de job qui s’est totalement terminé, et dont, implicitement, les fichiers sont « fermés » à la modification, il est donc nécessaire de les rouvrir. Une étape (un job) est donc également nécessaire avant la modification d’une version.
On a donc :
- Créations des versions : Localement, au moment de la soumission de la chaîne de job (synchrone).
- Ouverture/modification/fermeture des versions : Sur la ferme, par chaque worker (asynchrone).
Il n’est pas nécessaire de passer par un job dédié pour l’ouverture et la fermeture des versions, cela peut se faire directement dans le code qui s’exécute sur la ferme. À titre personnel, je préfère des jobs dédiés, car la modification d’une version peut nécessiter que deux jobs (ou plus) lui passe dessus.
J’appelle l’ensemble de cette approche « l’allocation de versions » : À un moment t, vous demandez au pipeline des « espaces » (ici, des versions) qui vont être modifié, plus tard, par différentes machines de la ferme qui s’occuperont ensuite de les libérer. Si aucune erreur ne s’est produite lors de l’exécution de votre chaîne de job, les versions créées par la ferme sont remplis, disponibles pour le reste du pipeline et les permissions y sont correctement appliquées.
Durée d’ouverture des scènes d’animation
Je vous invite à garder à l’esprit que la durée d’ouverture des scènes d’animation peut être importante. Certains plans de certains projets sur lesquelles j’ai pu travailler mettaient quasiment 30 minutes à s’ouvrir. C’est souvent un problème à résoudre en amont (car c’est l’animateur qui perd du temps), mais comme souvent en production, ce n’est pas possible pour le projet en cours. Si vous exportez vos Alembics directement depuis la scène d’animation, ça veut dire qu’une mise à jour du rig d’un seul personnage nécessite la réouverture complète de la scène que ce soit par l’animateur ou un job de ferme, c’est du gâchis.
Une méthode pour éviter ça consiste à n’exporter que les courbes d’animation et de reconstruire l’ensemble en partant d’une scène vide.
Il y a plusieurs façons d’exporter des courbes d’animation, je vous en donne deux, en vrac :
- Exporter les nœuds (principalement les courbes d’animations) seuls en format .mb/.ma ainsi qu’un fichier texte avec les informations de reconnexions de ces nœuds. Cette méthode permet de conserver l’animation originale de Maya, mais nécessite pas mal de développement et ne résout pas le problème des contraintes.
- Exporter un fichier ATOM, ce dernier comprenant une version baké des courbes d’animations. C’est ma méthode préférée, car elle permet de n’importer qu’un range précis d’une animation sur un autre range, permettant ainsi de reconstruire une animation en y ajoutant un preroll automatique pour nos amis du cloth. En passant par le bake, cette méthode résout le problème des contraintes qui ne sont plus utiles.
Une fois les courbes exportées, vous n’avez plus qu’à ouvrir une scène vide, importer la dernière version du rig et y coller vos courbes pour exporter l’Alembic.
Ces mécanismes, qui, mine de rien, ajoutent des étapes d’export, permettent de gérer des exports complexes car chaque asset est exporté individuellement.
Un dossier temporaire pour votre ferme
Il peut être pratique de disposer la ferme d’un système de fichier temporaire partagé par tous les worker. L’avantage immédiat étant de ne plus s’embêter avec des problématiques de pipeline et de version. Vous créez un dossier /farm/tmp/mon_id/ et vous y mettez ce que vous voulez. Les différents jobs liront et écriront à l’intérieur, avec, éventuellement, un job de nettoyage en fin de chaîne.
Un exemple d’utilisation que j’ai souvent observé tourne autour de l’assemblage de scènes :
- On exporte/assemble les scènes dans leur format de rendu (RIB, ass).
- On les rend.
- On sépare, parfois, les layers des images.
- On supprime les fichiers de rendu ; RIB, ass, voir les images brutes qui ne sont plus utiles (sauf pour du débogage).
On pourrait grossir cette liste d’étapes avec du précalcul de fichier (bake d’illumination, simulation et génération de poils) qui vient se faire avant le rendu. Bien que cela se fasse moins qu’il y a quelques années, le précalcul peut se révéler nécessaire pour rendre des plans qui sortent de l’ordinaire ; transitions bizarres, plans séquences, etc.
Les graphistes utilisant Houdini et ayant la responsabilité de plans complexes ainsi que les studios travaillant sur plusieurs projets de natures différentes (e.g. La publicité) s’appuient beaucoup sur ce système.
Plus un plan est complexe et spécifique, plus il est difficile de mettre en place un mécanisme de prédiction poussé. Le temps passé à généraliser une solution étant trop important et/ou le nombre de plan concerné étant trop faible.
Il y a un dernier cas où vous n’avez pas beaucoup le choix : Si la taille de votre ligne de commande est trop importante, vous devez sérialiser les arguments. Ça semble absurde, mais pour m’être déjà retrouvé dos au mur (une ligne de commande dont le nombre d’argument a augmenté au fil des semaines), écrire un JSON dans un dossier temporaire plutôt que d’avoir à repasser sur toute la gestion de la commande (on était en fin de production) peut vous sauver la mise.
Passer par un dossier partagé a le mérite de proposer une solution simple à comprendre pour tout le monde. On est clairement sur une approche artisanale de la ferme, tout en gardant une distinction claire entre ce qui est dans le pipeline et à l’extérieur.
Malgré ça, ne pas avoir de suivi granulaire des données générées par la ferme peut entraîner son lot de complication. Ainsi, une ferme multi-site devient un calvaire à gérer. Les dossiers temporaires n’étant pas au même endroit, soit vous faites un partage direct (ce qui implique une occupation continue de la bande passante), soit vous calez des jobs de synchro entre les jobs utilisant des machines de sites différents. Dans les deux cas, cela ajoute de la complexité à l’ensemble et il faut peser le pour et contre.
À titre personnel, j’ai pu remarquer que, dès lors qu’il faut synchroniser des choses, avoir un suivi précis est plus efficace : Gardez un suivi des choses à l’échelle du pipeline (asset, version, etc.) pour tout ce que vous pouvez anticiper et ne sortez la solution des fichiers temporaires de ferme que pour les exceptions.
D’un point de vue code, une petite API distribuée aux superviseurs leur évite d’avoir à gérer ça eux-mêmes : Une fonction qui crée le dossier temporaire, renvoi son chemin ainsi que le job chargé de supprimer de dossier en question est un bon début. Pour le nom du dossier temporaire généré par cette API, lui préfixer la date (2020_04_12) permet d’avoir rapidement un coup d’œil sur ce qui ne semble plus nécessaire.
Faites un suivi régulier de la taille de ces dossiers et impliquez les superviseurs qui l’utilisent, ils sont bien plus en mesure de savoir ce qui est nécessaire ou non.
Il va de soi qu’aucun autre script ne doit s’appuyer sur ce dossier. Certains pourraient avoir l’idée de s’en servir comme dossier d’échange dans le studio.
Nettoyage des jobs
On en a déjà un peu parlé, mais le nettoyage des jobs concerne plusieurs choses qui peuvent se faire à plusieurs moments du cycle de vie d’un job.
- Il y a le nettoyage qui se fait immédiatement après le job ou la chaîne de job. C’est celui qu’on fait naturellement quand le job est supposé avoir fini son travail (nettoyage des RIB).
- L’autre est plus subtile et se fait au moment de la suppression du job du manager. En pratique, on supprime rarement le job, mais on procède à son archivage. Cela faisant, les fichiers de logs sont également supprimés du système de fichier.
La plupart du temps, on aura un job dédié au nettoyage, mais certains jobs managers intègrent le concept de nettoyage en tant que paramètre du job. Cela peut prendre la forme de clef comme clean_dir, clean_file, clean_files, etc.
Des jobs génériques, ou spécifique ?
Au moment de l’écriture d’un job, une balance tend à apparaitre : Doit-on écrire un job qui fonctionnera pour tout type de tâche ? Ou doit-on écrire un job qui fonctionnera pour un besoin précis ? Doit-on gérer les choses de façon abstraite ou de façon concrète ? Ma réponse ne va pas énormément vous aider : Les deux mon capitaine !
Prenons un exemple : Vous souhaitez faire les jobs « d’export des personnages ». Exprimé de la sorte, c’est un besoin abstrait. En effet, « exporter un personnage » se fait, à priori, en plusieurs étapes :
- Exporter des courbes d’animation.
- Exporter un ou plusieurs Alembics.
- Calculer une ou plusieurs simulations de poils (cheveux, poils).
- Baker un ou plusieurs systèmes de poils.
- Calculer une, ou plusieurs simulations de vêtements.
- Calculer et exporter des simulations au sol (zones de contact pour le FX).
J’ai donné une liste aussi exhaustive que possible, mais il est évidant que peu de projets cochent toutes les cases et qu’il n’est pas forcément optimal de faire un export de personnage aussi granulaire que ça (tout dépend de votre budget).
La question de savoir si ont fait des jobs pour « exporter un personnage » ou « exporter un Alembic » se pose. Si on choisit de faire un job « d’export de personnages », vous vous rendrez vite compte qu’il doit être séparé en petits jobs. Ensuite, si on choisit de faire des jobs qui « exportent un Alembic », on risque de buter, plus loin, sur des problématiques spécifiques : Est-ce qu’on exporte un Alembic de la même façon pour un personnage que pour une simulation ? Dès lors, un besoin de faire un job qui « export un Alembic FX » apparaît et il est probable qu’il n’ait pas été anticipé. Dans le pire des cas, vous vous retrouvez avec un département FX complet à qui on a dit que les jobs « d’export d’Alembic » étaient près et qu’il pouvait commencer le travail.
Si tout ceci peut sembler relever du domaine académiques, c’est parce qu’il s’agit rarement de questions qui se posent en début de production, quand on met notre ferme en place, mais plutôt quand la nature de ce que fait votre ferme évolue (milieux de production ou entre deux saisons d’une série). Ces questions, mise de côté, agissent comme un ressort.
La raison pour laquelle j’insiste sur cette distinction, c’est pour que vous soyez en mesure de la « détecter » en production, au risque de perdre du temps en enchevêtrement de paradigmes et/ou discussion avec la production.
Quand des graphistes ou des superviseurs vous parleront, ils ne feront pas cette distinction. C’est vous le codeur, c’est votre travail de la faire et de l’expliquer. Dans notre exemple, si un superviseur pense qu’il va pouvoir exporter des Alembic de FX parce que vous lui avez fait un job d’export d’Alembic sans en définir correctement le contour, vous êtes en parti responsable de cette confusion. En gros, ne « pensez » pas les jobs suivant leur nom, mais suivant ce qu’ils font, et assurez-vous que vous n’êtes pas le seul.
On peut, légitimement, se demander s’il est utile d’avoir des jobs génériques qui font des choses dont la définition n’est pas (encore ?) clair aux yeux de la production. Quand un besoin est « ballant » (comprenez, on sait qu’on en a besoin, mais on ne sait pas si c’est la bonne façon de faire), il me semble que faire un job qui fait « le truc » est la solution.
Gestion des différentes versions des logiciels sur la ferme
Suivant la nature des projets que vous avez à sortir, il est fort probable que vous ayez à gérer différentes versions de logiciels et des plugins qui les compose.
Vous pouvez définir des versions « à la machine », mais cela vous prive de puissance de calcul, car vous risquez de ne pas pouvoir utiliser une machine au simple prétexte qu’elle n’a pas la bonne version de Maya d’installée.
On serait donc tenté d’avoir plusieurs versions d’un logiciel, disponible sur chaque machine. Dès lors qu’une machine rend disponible plusieurs versions d’un logiciel, vos jobs doivent pouvoir appeler la bonne version.
Les méthodes pour y arriver sont nombreuses aucune n’est parfaite et leur utilisation dépend beaucoup de l’organisation de votre studio (rien que ça). La plus naïve consiste à appeler l’exécutable d’un logiciel par un nom précis. Dans le cas de Maya, on aurait donc une ligne de commande :
maya2019 -c "print 'toto'"
J’ai quelque à priori vis-à-vis de cette méthode. Le principal étant la gestion des versions des plugins. En effet, si vous utilisez un plugin (e.g. Yeti pour Maya), il est probable que vous ayez à glisser de version en cours de production (vous commencez les nouveaux plans avec la nouvelle version, vous finissez les anciens plans avec l’ancienne).
Je rappelle l’évidence : Il est dangereux de changer de version d’un logiciel en cours de production. En revanche, certains bugs peuvent être tellement bloquants qu’ils remettent en question ce dogme. Il peut s’agir de problèmes corrigés dans une version mineure (2.5.0 -> 2.5.1), comme de problèmes plus graves qui remettent en cause l’utilisation de l’outil. C’est une situation qui peut apparaître quand on utilise un tout nouvel outil en production et qu’on réalise, trop tard, que ce qui était prévu de faire avec n’est pas possible à cause d’un bug corrigé dans une version majeure (2.5.0 -> 3.2.0).
À cela vient s’ajouter un dernier point, pratique, qui est le test : Vous êtes en 2.5.0 et que la version 2.5.1 corrige le problème, vous passez tout le plancher en 2.5.1. Plus tard, en production, un problème, différent mais qui semble lié apparait. Vous avez un doute : Est-ce que ce problème apparaissait en 2.5.0 ?
Et là on parle d’un seul plugin, mais certains logiciels sont amenés à faire tourner pas mal de plugins différents. Dès lors, vous voyez une matrice se dessiner : Version du logiciel/Version du plugin A/Version du plugin B/etc. Et si vous utilisez des plugins compilés « maison », c’est encore pire, car vous pouvez être amené à livrer une version plusieurs fois par jour.
Il est tout à fait possible de ne s’appuyer que sur le nom de l’exécutable dans la ligne de commande :
maya2019-yeti2.5.0-rigNodeMaison3.6.5 -c "print 'toto'"
maya2019.sp1-yeti2.5.0-rigNodeMaison3.6.5 -c "print 'toto'"
maya2019.sp1-yeti2.5.1-rigNodeMaison3.6.4 -c "print 'toto'"
...
Notez que Ecosystem de PeregrinLabs fonctionne un peu suivant ce principe, mais je suis dubitatif quant à la taille de tels lignes de commandes quand vos graphistes deviennent mordu de plugins maisons. Je lui préfère une approche via variables d’environnement :
export MYENV_MAYA_VERSION=2019.sp1;
export MYENV_YETI_VERSION=2.5.0;
export MYENV_RIGNODEMAISON_VERSION=3.6.5;
myenv -- maya -c "print 'toto'"
Ici, myenv est un exécutable qui consomme les variables d’environnement commençant par MYENV_ pour en faire des environnements dans lequel la commande qui suit « -- » est exécuté.
Bien entendu, les commandes export ne sont pas exécutées par vous, mais envoyé avec le job au moment de la soumission :
my_env = {'MYENV_MAYA_VERSION': '2019.sp1',
'MYENV_YETI_VERSION': '2.5.0',
'MYENV_RIGNODEMAISON_VERSION': '3.6.5'}
job = {'command': 'myenv -- maya -c "print \'toto\'",
'env': my_env}
farm.submit(job)
Je suis un adepte de cette méthode.
Arrivé ici, je ne peux pas ne pas vous parler de Rez. Je ne l’ai jamais utilisé personnellement, mais j’en ai entendu beaucoup de bien.
Rez résout des environnements via un système de dépendance. La charge cognitive initiale due à son apprentissage est importante, mais il est considéré comme une brique solide d’un pipeline avec une bonne documentation.
La gestion des environnements étant souvent central dans un studio, vous pouvez aussi être tenté d’écrire le vôtre. Ce n’est pas particulièrement difficile à faire (pour tout vous dire, je n’ai encore jamais fait autrement), mais c’est une maintenance en continue. L’avantage étant que ce gestionnaire s’en tiendra à faire exactement ce que vous voudrez, pas plus, pas moins.
Si vous choisissez de le faire en Python, gardez le module aussi isolé et indépendant que possible. S’il vous vient à l’idée de questionner la BDD sur les métadonnées d’un shot pour résoudre un environnement, vous fonctionnez peut-être à l’envers (et si vraiment vous n’avez pas le choix, passez par une variable d’environnement : MYENV_SHOT_NUMBER)
Data mining
C’est le sujet sexy du moment et il est difficile d’avoir un avis tranché tant le secteur « tâtonne » à déterminer si le temps de compréhension et d’interprétation des données justifie d’y dépenser de l’énergie.
La première erreur consisterait à utiliser des données de ferme pour répondre à des questions de production : Si vous voulez répondre à des questions de production (e.g. nombre de validation par semaine), analysez des données de production (e.g. Shotgun). En revanche il est très utile de comparer les données de ferme à des données de production, cette dernière influençant la première. Vous serez peut-être en mesure d’y trouver des corrélations intéressantes, voir, surprenantes.
Pour l’anecdote, sur un projet, on avait pu remarquer que plus on se rapproche de la fin du projet, plus le temps de rendu moyen par image diminuait, en parallèle de quelques plans qui voyaient leur temps de rendu augmenter drastiquement. On avait mis ça sur le compte du fait que, la deadline arrivant, les graphistes ne prenaient plus le risque d’augmenter les temps de rendu et forçait sur l’optimisation de leurs scènes pour éviter de les voir « revenir » de la ferme au motif d’un temps de rendu trop long, ce qui, par effet de débordement, diminuait la qualité générale. La pression qui peut apparaître en fin de production peut entraîner, à tous les niveaux de la hiérarchie, une diminution du zèle (que je crois) nécessaire à la sortie de belles images. Les superviseurs et les leads doivent alors se focaliser sur ce qui est essentiel à la qualité d’un plan. C’est d’ailleurs le moment ou le ratio qualité/temps de travail graphiste est le meilleur, les gens ayant pris l’habitude des erreurs à ne surtout pas faire et de ce qui plaît. Quant aux quelques rendus qui explosent ? C’est les laissés pour compte, les rendus qui ont un problème, mais qu’on a plus le temps de régler.
Mais je digresse…
Les données de ferme ne répondront qu’à des questions de gestion de ferme : Alimentation, charge, licence. Ces données sont très utiles pour élaborer correctement des budgets par juxtaposition. Il est, en effet, plus simple de définir les besoins d’une production quand on a déjà une base chiffrée de l’utilisation d’une ferme sur un projet.
Avoir des logs explicites
Isoler un job pour reproduire un bogue prend du temps, et ce, malgré le travail effectué pour simplifier cette démarche. Quand un problème apparaît, vous aurez rapidement le réflexe de lire le log du-dis job en le comparant avec les appels à print() de votre code. En faisant cela vous aurez rapidement une idée de où votre script a planté. Et si vous avez affiché les valeurs des différentes variables, vous serez potentiellement en mesure de reproduire le problème avec une simple commande.
Il est donc important d’avoir des logs descriptif et suffisamment claires. Il ne faut pas hésiter à être verbeux, car si vous n’affichez que quelques informations, vous risquez de vous retrouver face à un gros bloc de code dans lequel le problème apparaît, sans que vous puissiez être en mesure de déterminer ce qu’il fait.
Je vous invite également à ajouter des informations de temps afin de déceler les écarts qui peuvent se produire entre deux lignes :
2018-01-22 10:53:00,500|CMD |INFO|...
2018-01-22 10:53:01,589|CMD |INFO|...
2018-01-22 10:53:01,589|CMD |INFO|...
2018-01-22 10:53:02,351|MAYA|INFO|...
2018-01-22 10:53:02,351|MAYA|INFO|...
2018-01-22 10:53:02,605|MAYA|WARN|...
2018-01-22 10:53:02,605|MAYA|INFO|...
Conclusion
J’aurais pu aborder le cloud, mais le sujet est très large et je ne pense pas avoir assez d’expérience pour donner des conseils pertinents.
J’espère que ces deux billets vous auront plus.
À bientôt !