Table of Contents
Commit 2008-08-18
Modifs
Threads / Interpréteur python
Pour mon nouveau TFiste j'ai besoin de manipuler des PythonCurve
s. Petit problème, elle cohabitent assez mal avec l'interface graphique. Par exemple, Metafor explose quand on appuie sur “update” de VizWin en fin de calcul quand celui-ci utilise une PythonCurve
. Impossible donc de voir les résultats!
J'ai donc corrigé la gestion des threads dans notre interpréteur python graphique. C'est pas la première fois que j'essaye mais cette fois-ci c'est la bonne.
Le problème vient du fait que l'interpréteur python n'est pas thread-safe quand on le mixe avec des module compilés en C++. Autrement dit, on ne peut pas appeler simultanément des fonctions de l'API python dans 2 threads différents. Pour pouvoir quand même y arriver, python fournit une sorte de mutex global appelé GIL (Global Interpreter Lock) dont il faut prendre le contrôle quand on veut appeler python à partir du C++.
Comment cela pouvait-il marcher avant alors? (on a toujours pu voir les courbes interprétées dans VizWin avant ou pendant le calcul). Hé ben un peu par hasard: par erreur, j'initialisais python dans le thread graphique, ce qui lui donnait une existence dans python (un PyThreadState
) qui était conservé. Lorsque python appelait win.update()
, j'avais programmé un blocage à l'aide des outils Qt pour attendre la fin de la mise à jour. Il faut croire que ce système de blocage rendait la main au thread principal au niveau python… Par contre, si on appuyait sur le bouton, le thread python n'attend pas et PAF!
En résumé,
- j'ai initialisé python dans le thread python (du coup, les
PythonCurve
faisaient logiquement planter Metafor). - j'ai activé la gestion des threads dans SWIG par le mot clef
threads=“1”
dans chaque.i
. Cette commande permet de relacher la GIL à chaque appel du C++. Inévitablement, puisque python n'a plus la main quand on est en C++, cette modif fait planter tous les appels à l'API python. - j'ai ajouté du code manipulant la GIL partout où on utilise l'API python en C++. Grâce à cela, tout a fonctionné sauf Gen4 qui utilise l'interfaçage SWIG des itérateurs standards qui semble bugué. Pour contourner le problème: deux solutions, soit compiler Gen4 sans support des threads (c'est un peu dommage puisqu'il faudrait alors se rappeler que ce module ne supporte pas les threads), soit désactiver le support des threads dans LA routine qui merdouille (le destructeur des iterateurs SWIG). C'est cette deuxième solution que j'ai choisie.
Dans mes essais, j'ai migré le code vers swig-1.3.36 que j'ai installé sur toutes les machines. Il est indispensable d'utiliser cette nouvelle version pour compiler Metafor (j'ai dû modifier le source).
Petite ref vers le site qui m'a mis sur la voie: Matt's blog
Le système ci-dessus fonctionne correctement avec les directors utilisés par Luc pour dériver des fonctions objectives sous python. Cependant, j'ai eu un problème avec la fonction membre write
de PythonObjectiveFunction
qui, si elle est déclarée dans le director est appelée infiniment de manière récursive. Ce problème n'a rien à voir avec les threads.
Convection de défauts sur maillages ALE
J'aimerais ajouter une interface python à fournir a mon TFiste pour coder des ReZoner
s. J'ai donc créé une nouvelle classe CurveReZoner
qui sera prochainement interfacée avec python.
J'ai ajouté un test de convection de défaut dans la batterie (une gaussienne qui se ballade sur un maillage fixe): apps.ale.defaut
.
Projet
Windows: Téléchargez SWIG-1.3.36 (je l'ai mis sur calimero) ou mettez à jour vos libdeluques.
Unix: Ajoutez /opt/swig-1.3.36/bin
a votre PATH sur toutes les machines.
Fichiers ajoutés/supprimés
mtALE/CurveReZoner.cpp added mtALE/IterativeReZoner2D.cpp added (+) mtALE/CurveReZoner.h added mtALE/IterativeReZoner2D.h added (+) mtALE/ReZoner2D.cpp deleted mtALE/ReZoner2D.h deleted
— Romain BOMAN 2008/08/18 11:45