I. Introduction▲
Nous allons voir dans cet article que le temps d'exécution d'un code Python peut parfois être relativement long et qu'il existe différentes manières pour y remédier.
Cet article n'a pas pour but d'expliquer en détail comment le développeur peut faire ceci. Il s'agit juste ici d'une simple présentation associée à une comparaison avec les performances d'un code écrit en C++.
Comme code exemple nous choisirons celui du plus grand diviseur commun entre deux nombres.
Pour ce faire nous réaliserons ce code dans les configurations suivantes :
- en pur Python ;
- en Cython ;
- en QML appelé par Python ;
- en QML appelé par Cython ;
- en QML appelé par C++ ;
- en pur C++ ;
Comme vu plus haut, le but de cet article n'est pas d'expliquer comment sont créés les codes, mais uniquement de faire les tests nécessaires. Ne cherchez donc pas ici un tutoriel sur le langage Cython ou QML par exemple.
II. Création des codes▲
Ci-dessous vous trouverez les différentes versions du code que nous utiliserons. Afin d'augmenter volontairement le temps d'exécution nous allons faire en sorte de répéter l'opération plusieurs centaines de fois.
II-A. Code Python▲
def
fonction
(a,b):
while
b !
=
0
:
a,b=
b,a%
b
return
a
for
i in
range
(0
,10000001
):
fonction
(9078
,5118
)
print
("
fin
du
test
i
=
"
, i)
II-B. Code Cython▲
cpdef fonction
(a,b):
while
b !
=
0
:
a,b=
b,a%
b
return
a
for
i in
range
(0
,10000001
):
fonction
(9078
,5118
)
print
("
fin
du
test
i
=
"
, i)
II-C. Code QML + divers appels▲
II-C-1. Code QML▲
import
QtQuick 2.0
Item
{
function myTest(){
function pgcd(a, b){
return b ? pgcd(b, a %
b) :
a
}
for
(var i=
0
; i<=
10000000
; i=
i+
1
){
pgcd(9078
, 5118
)
}
console.log("
Fin
du
test
i
=
"
, i)
return 0
}
}
II-C-2. Appel via Python▲
import
sys
from
PyQt5.QtCore import
QCoreApplication, QUrl, QMetaObject, Qt
from
PyQt5.QtQml import
QQmlComponent, QQmlEngine
def
fonction
():
app =
QCoreApplication
(sys.argv)
engine =
QQmlEngine
()
component =
QQmlComponent
(engine)
component.loadUrl
(QUrl
('
ex
.
qml
'
))
test =
component.create
()
QMetaObject.invokeMethod
(test, "
myTest
"
, Qt.DirectConnection)
del
engine
fonction
()
II-C-3. Appel via Cython▲
import
sys
from
PyQt5.QtCore import
QCoreApplication, QUrl, QMetaObject, Qt
from
PyQt5.QtQml import
QQmlComponent, QQmlEngine
cpdef fonction
():
app =
QCoreApplication
(sys.argv)
engine =
QQmlEngine
()
component =
QQmlComponent
(engine)
component.loadUrl
(QUrl
('
ex
.
qml
'
))
test =
component.create
()
QMetaObject.invokeMethod
(test, "
myTest
"
, Qt.DirectConnection)
del
engine
fonction
()
II-C-4. Appel via C++▲
#
include
<QApplication>
#
include
<QQmlEngine>
#
include
<QQmlComponent>
#
include
<QQuickView>
int
main
(int
argc, char
*
argv[])
{
QCoreApplication app
(argc, argv);
QQmlEngine engine;
QQmlComponent component
(&
engine, QUrl
("
ex.qml
"
));
QObject *
object =
component.create
();
QMetaObject::
invokeMethod
(object, "
myTest
"
, Qt::
DirectConnection);
return
app.exec
();
delete
object;
}
II-D. Code C++▲
#
include
<stdio.h>
int
pgcd
(int
a, int
b)
{
return
b ? pgcd
(b, a %
b) : a;
}
int
main
(void
)
{
for
(int
i=
0
; i<=
10000000
; i=
i+
1
);
pgcd
(9078
, 5118
);
printf
("
Fin
du
test
i
=
10000000
"
);
return
0
;
}
Voila, tous nos codes sont écrits. Pour ceux utilisant Cython ou C++ une compilation complémentaire est nécessaire. Je vous invite pour cela à lire les différentes documentations présentes sur developpez.com.
Nous allons pouvoir maintenant passer aux tests.
III. Tests des codes créés▲
Pour les utilisateurs linux, je vous propose de créer un bash permettant de faire nos tests. Au moment de rédiger cet article, je n'ai pas la possibilité de faire des tests sur d'autres OS mais je présume qu'il est possible de faire quelque chose de similaire à ce qui va suivre.
Voici le bash proposé :
echo
echo "
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
"
echo "
Temps
exécution
en
Python
:
"
time python3 codepython.py
echo
echo "
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
"
echo "
Temps
exécution
en
Cython
:
"
time python3 lancecython.py
echo
echo "
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
"
echo "
Temps
exécution
en
QML
appelé
via
Python
:
"
time python3 qmlviapython.py
echo
echo "
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
"
echo "
Temps
exécution
en
QML
appelé
via
Cython
:
"
time python3 lanceqml.py
echo
echo "
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
"
echo "
Temps
exécution
en
C
+
+
:
"
time ./codecpp
echo
echo "
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
"
echo "
Temps
exécution
en
QML
appelé
via
C
+
+
:
"
time ./qmlviacpp
Il ne reste plus qu'à lancer lance.sh via la commande et à constater les résultats :
./lance.sh
Voici dans mon cas le résultat obtenu :
On pourra remarquer plusieurs choses :
- le code Python est vraiment long ce qui peut obliger le développeur à utiliser plusieurs threads s'il ne veut pas figer sont programme lors de certains calculs ;
- le code Cython permet un gain d'environ 50 % par rapport au code Python, ce qui peut être assez sympa puisque beaucoup de code peuvent être transcrit rapidement. Cependant ceci nécessite le passage par une compilation ;
- le code QML lancé par Python ou Cython est environ identique en termes de temps d'exécution, par contre cette manière permet de gagner beaucoup par rapport au code Python. On peut en déduire que des fonctions écrite en QML seront plus rapidement exécuter que des fonctions Python ;
- le code QML lancé par C++ est plus long que le même lancé via Python mais demeure plus rapide que du pur Python ;
- le code C++ écrase tout est reste le code le plus rapide en termes d'exécution.
IV. Conclusion▲
J'utilise depuis quelque temps PyQt, mais est découvert que très récemment Qt Quick. Ces simples tests m'ont permis de mettre le doigt sur un point important : il est très certainement plus intéressant de coder un maximum de chose en QML, celui-ci permettant un net gain de performance sans même devoir utiliser Cython.
V. Remerciements▲
Je tiens à remercier tout particulièrement …. et …. pour leur relecture attentive.