[MAYA PYTHON API] Optimisation de l’utilisation du wrapper python
- lundi 30 novembre 2015
- Publie dansTous les articles
- Ecrire commentaire
Dorian Fevrier a déjà écrit un article similaire sur l’utilisation des commandes maya versus l’API dans ce billet: Récupérer rapidement la position des vertices d’un mesh Maya
Pour résumer:
pSphere 50×50 smoothée 4 (soit 633602 vertices):
iteration xform: 39 sec (xform(« mesh.pt[n] »))
iteration API: 4 sec (MFnMesh.getPoints())
xform sans itération: 2 sec (xform(« mesh.pt[*] »)
Ici je vais parler d’une optimisation liée à l’utilisation d’un wrapper Python -> C++ (l’API python de maya quoi).
On est tombés, avec mon compère, vendredi dernier, en codant un algo de copie de poids de deformer indépendant d’une topologie, sur un petit souci de temps: récupération pour chaque vertex d’un mesh des vertex connectés: 45 secondes de process pour 1 000 000 de vertices… Après divers optimisations (suppression des boucles pour passer en récupération d’infos par pack puis traitement en pur python) nous sommes passés ) à une vingtaine de secondes… Mieux mais toujours énorme! Le process qui apparaissait comme long était le suivant:
it = MItMeshVertex(node.asMObject()) while not it.isDone(): vtxList = MIntArray() it.getConnectedVertices(vtxList) related.append([vtxList[i] for i in xrange(vtxList.length())]) it.next()
17.04 secondes pour 1002001 points
J’avais déjà été confronté à un problème de la sorte pour un wrapper purement Python, pour énormément d’objets, l’accès aux attributs pouvait être horriblement long… Idem pour la création de leurs instances! Donc que pouvait-on optimiser ici?
Sachant que la partie C++ remplit le tableau de points lui-même, il gère directement son traitement dans la sous couche C++, donc laissons le faire!
vtxList = MIntArray() while not it.isDone(): it.getConnectedVertices(vtxList) related.append([vtxList[i] for i in xrange(vtxList.length())]) it.next()
Et bim! On passe à 8.15 secondes pour 1002001 points
Si on veut pousser mémé dans les orties et descendre à 6.60 secondes:
vtxList = MIntArray() appd = related.append size = vtxList.length acces = vtxList.__getitem__ t = time.time() while not it.isDone(): it.getConnectedVertices(vtxList) appd([acces(i) for i in xrange(size())]) it.next()
On pourrait utiliser map(acces, range(size())) qui ferait gagner un chouia, mais range supporte très mal les grands tableaux, donc on restera sur une liste compréhension et un xrange.
Edit:
Depuis peu, j’essaie d’utiliser au maximum l’API 2 qui s’avère bien plus rapide lors des post traitement des objets python (ex: conversion MIntArray -> list):
On descends à 3.20 secondes pour les mêmes nodes.
it = MItMeshVertex(ob) while not it.isDone(): vtxList = it.getConnectedVertices() related.append(list(vtxList)) # related.append(vtxList) # On descend à 1.09 sec it.next()
coucou,
je suis arrive la un peu par hasard, donc j’ai pitetre rate quelque chose (et j’arrive en tout cas tres probablement un peu tard !), mais par curiosite, tu as essaye avec une matrice d’incidence non orientee plutot ? De maniere generale, privilegier numpy permet un gain de temps considerable, et np brille tout particulierement avec d’enormes sparse matrix. L »interet de fonctionner comme ca serait que tu n’as pas besoin de faire le boulot en double voire triple (si A est connecte a B, a priori on peut en deduire que B est connecte a A ^^). Meme chose au niveau des acces, tu gagnerai probablement du temps par rapport a une simple flat list. Je dis peut-etre nimporte quoi, mais je ne serai pas surpris que numpy offre des acces plus rapides qu’une immense liste python (une liste python etant en gros environ 5 fois plus lourde qu’une array numpy, il doit yavoir des consequences sur la memoire). Rien que sur une bete liste vide de 1 000 000 elements, python prend .13 sec a la creer la ou numpy en prend .005
Enfin, meme si tu n’as pas acces a numpy, je suis quasi sur que ca vaudrait le coup de te creer ta propre sparse matrix =]
Voila voila, meme si tu as deja tres probablement regle ton probleme depuis 2015 ^^
Merci pour ta réponse (qui effectivement améliorerais le temps de calcul du 3eme script), mais ici, le but était de montrer un cas d’optimisation lié à l’utilisation de l’API Maya.