IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)

Vous êtes nouveau sur Developpez.com ? Créez votre compte ou connectez-vous afin de pouvoir participer !

Vous devez avoir un compte Developpez.com et être connecté pour pouvoir participer aux discussions.

Vous n'avez pas encore de compte Developpez.com ? Créez-en un en quelques instants, c'est entièrement gratuit !

Si vous disposez déjà d'un compte et qu'il est bien activé, connectez-vous à l'aide du formulaire ci-dessous.

Identifiez-vous
Identifiant
Mot de passe
Mot de passe oublié ?
Créer un compte

L'inscription est gratuite et ne vous prendra que quelques instants !

Je m'inscris !

Python 3.11 et C++ : quelles sont les performances de ces deux langages en matière de simulation ?
Comparaison de vitesse à l'aide d'une simulation scientifique

Le , par Stéphane le calme

349PARTAGES

44  1 
Vous avez lu gratuitement 341 articles depuis plus d'un an.
Soutenez le club developpez.com en souscrivant un abonnement pour que nous puissions continuer à vous proposer des publications.

Une erreur dans cette actualité ? Signalez-nous-la !

Avatar de floyer
Membre éclairé https://www.developpez.com
Le 27/12/2022 à 23:39
On peut aussi avoir un programme Python dont le temps d’exécution est principalement passé dans les bibliothèques (Numpy, Panda, Tensorflow…), et du coup, le temps passé dans l’interpréteur Python apparaît moins important. Et le caractère pratique de la bibliothèque est prédominant.
12  1 
Avatar de amorgos
Membre du Club https://www.developpez.com
Le 31/12/2022 à 22:46
Alors bon .. comment dire ?
Je rejoins ceux qui ne voient pas trop l'intérêt de cet article.
Comparer Python 3.10 à Python 3.11, pourquoi pas.
Cela permet de vérifier que l'on ne nous vend pas un nième épisode de
la grande saga "Les prochaines versions seront plus rapides".
(Je vois passer ces histoires depuis 20 ans à propos de Java, et s'il y a effectivement
des améliorations, elle passent toujours par la même porte:
un petit peu moins d'interprétation et un peu plus de compilation).
Au final, rien ne change fondamentalement.

Ce qui m'a intéressé ici est la version C++ de ce benchmark.
Oulà ! On peut dire que ça pique les yeux. Je me demande quel développeur à
écrit cela.

Je passe sur l'intérêt d'utiliser l'héritage ici.
Techniquement, il ne sert à rien dans ce cas précis, comme cela a déjà été dit.
Mais dans le cadre d'une simulation plus importante, pourquoi pas.
Mais dans ce cas, il faudra aussi du polymorphisme.

Pour ce qui est de l'écriture du code, on sent clairement que c'est une transcription de la version Python.
- Encapsulation ? Y'en a pas.
- Construction propre ? Y'en a pas non plus. Les objets sont construits, puis modifiés (par chance, tout est public, c'est commode comme du Python)
- RAII pour la fermeture automatique du flux ? Ah bon, ça existe ?

- Les calculs sont menés en dépit du bon sens :
ex: tirage d'un nombre aléatoire entre [0.0 et 1.0] : (rand() / (RAND_MAX + 1.0)
ben non, désolé, ce n'est pas ça. On obtient ici un nombre entre [0 et quelque chose qui est inférieur à 1]
Je sais ici ce qui s'est passé : la division entière à donné un résultat inattendu, et le "programmeur" s'est rendu compte que ça "marchait" en ajoutant 1.0.

Autre exemple de code tordu : { return (a->is_alive == false) ? true : false; }
ah bon ? { return !a->is_alive ; } ça ne serait pas un peu plus clair ?

Un autre petit pour la route : double squared_dist = pow((x - target->x), 2) + pow((y - target->y), 2);
Tu m'étonnes que sans l'option -O2 la programme n'aille pas vite !
La fonction pow est tout sauf simple (souvent log et exp sont de la partie) alors pour calculer un carré
par pitié, utilisez un produit ! Il se trouve que le compilateur est plus compétent que le programmeur: avec -O2
l'exponentiation est remplacée par un produit. J'ai vérifié.

- Et il y a aussi des erreurs de logique dans le code.

- Mais le pire du pire est la gestion de la mémoire. Comme certains l'on dit (mais il semble que ça n'intéresse personne)
ce programme est un gigatesque memory leak. Voici ce que dit valgrind :

==13641== HEAP SUMMARY:
==13641== in use at exit: 1,567,552 bytes in 22,579 blocks
==13641== total heap usage: 45,155 allocs, 22,576 frees, 2,190,672 bytes allocated
==13641==
==13641== LEAK SUMMARY:
==13641== definitely lost: 1,421,696 bytes in 22,214 blocks
==13641== indirectly lost: 22,976 bytes in 359 blocks
==13641== possibly lost: 0 bytes in 0 blocks
==13641== still reachable: 122,880 bytes in 6 blocks
==13641== suppressed: 0 bytes in 0 blocks

Mazette ! 1,567,552 bytes, ce n'est pas du goutte à goutte.
Ceci montre à quel point il y a des programmeurs qui ne possèdent pas les bases
les plus élémentaires. Et je pense que plus Python prend de l'importance (enseignement et industrie)
plus le nombre de ces programmeurs augmente.

A première vue, il suffit de désallouer les acteurs pointés par les différents pointeurs contenus dans les listes,
à la fin du programme, et ceux qui sont retirés des listes en cours de simulation.
En fait, c'est un peu plus compliqué, car chaque prédateur comporte un pointeur target vers sa proie.
Il est donc fréquent qu'un acteur soit "mort", mais encore référencé pour au moins un cycle de simulation,
par un ou plusieurs prédateurs.
il n'est pas simple de le desallouer au bon moment.
A moins de faire de grosses acrobaties, un compteur
de références s'impose. J'ai remplacé tous les pointeurs nus par des shared_ptr (5 minutes), et tout se passe bien.
L'empreinte mémoire est aussi plus faible à l'instant t.
==14063==
==14063== HEAP SUMMARY:
==14063== in use at exit: 0 bytes in 0 blocks
==14063== total heap usage: 67,606 allocs, 67,606 frees, 2,966,744 bytes allocated
==14063==
==14063== All heap blocks were freed -- no leaks are possible
==14063==

Si shared_ptr est trop luxueux (pas besoin d'être thread safe) un pointeur intelligent maison plus rustique marche aussi très bien
et consomme moins de mémoire.

==14316==
==14316== HEAP SUMMARY:
==14316== in use at exit: 0 bytes in 0 blocks
==14316== total heap usage: 45,220 allocs, 45,220 frees, 2,252,760 bytes allocated
==14316==
==14316== All heap blocks were freed -- no leaks are possible
==14316==

Vous vous doutez que j'ai vérifié les performances (rapidement, sur 10 20 ou 30 exec)
Effectivement Python 3.11 est plus rapide que 3.10 sur cet exemple. Les chiffres avancés
me semblent en accord avec ce que j'ai constaté.
En ce qui concerne Python 3.11 vs C++ (compilé en C++20, -O2), j'ai un ratio de 10 à 18 selon les séries,
mais souvent plus proche de 10. Je précise ce ces chiffres concerne la version sans fuite de mémoire.

Un phénomène m'intrigue : les résultats en C++ sont assez stables (ils varient dans un rapport de 1 à 2 environ)
par contre en Python 3.10 on a des pics aléatoires d'un facteur 5 (de 15 à 75 sec par exemple !). Cela se produit aussi en Python 3.11
mais c'est moins fréquent (de 10 à 50 par exemple). Si un connaisseur de Python a une explication, je suis preneur.
11  0 
Avatar de redcurve
Inactif https://www.developpez.com
Le 28/12/2022 à 4:18
Citation Envoyé par floyer Voir le message
Le on peut aussi avoir un programme Python dont le temps d’exécution est principalement passé dans les bibliothèques (Numpy, Panda, Tensorflow…), et du coup, le temps passé dans l’interpréteur Python apparaît moins important. Et le caractère pratique de la bibliothèque est prédominant.
Elles sont toutes écrites en C ou C++ pratiquement aucun code python n'entre en jeu en utilisant ces bibliothèques
7  1 
Avatar de Pierre Louis Chevalier
Expert éminent sénior https://www.developpez.com
Le 29/12/2022 à 14:59
Citation Envoyé par pebaroiller Voir le message
Pourquoi comparer du code "interprété" avec du code compilé ? ...
Pour avoir des données précises, et au vu des informations prendre les décisions adéquates en fonction du type de projet.
5  0 
Avatar de dourouc05
Responsable Qt & Livres https://www.developpez.com
Le 27/12/2022 à 23:08
Citation Envoyé par grunk Voir le message
Python est un des langaes interprété les plus lent , C++ un des langages compilé les plus rapide. Tout le monde le sait.
Tout le monde le sait, mais c'est faux ? Certes, C++ est toujours dans le haut du classement en termes de performance (sauf code mal écrit), mais Python fait d'énormes progrès en termes de performance. Par exemple, la version 3.11 est prévue pour être 10 à 60 % plus rapide que la 3.10. Stéphane en parle bien dans son message. Certes, on sera toujours loin de C++, mais sur cet exemple Python passe de 12 fois plus lent à 7 fois, c'est un beau progrès, ça limite le besoin de passer à du code compilé.
10  7 
Avatar de pebaroiller
Membre à l'essai https://www.developpez.com
Le 29/12/2022 à 11:33
Pourquoi comparer du code "interprété" avec du code compilé ? ...

Que ce soit du code généré en pyton, js, php ou n'improte quel autre langage qui utilise un preprocesseur pour "pré-compilier" puis exécuter le code , celui-ci sera toujours plus lent qu'un code compilé ..
8  5 
Avatar de floyer
Membre éclairé https://www.developpez.com
Le 29/12/2022 à 15:37
De plus, avec Cython, on a du code compilé. Il
Est donc intéressant de situer ce compilateur.

Et même s’il est évident qu’un language semi-compilé (compilé en byte code) sera moins performant que le langage C compilé, avoir des ordres de grandeur de la différence peut être utile. Est-ce un facteur 2 ? 3 ? 10 ? …
3  0 
Avatar de grunk
Modérateur https://www.developpez.com
Le 27/12/2022 à 22:04
Je vois pas bien l'intérêt de comparer Python et C++ en terme de perf.
Python est un des langaes interprété les plus lent , C++ un des langages compilé les plus rapide. Tout le monde le sait.

Python est un super outil car il permet de mettre en place des choses rapidement , mais dès que les performances sont importante on le remplace
9  7 
Avatar de eric44000
Membre averti https://www.developpez.com
Le 29/12/2022 à 4:19
Citation Envoyé par Stéphane le calme Voir le message

Lequel de ces langages utilisez-vous ?
Les 2 mon capitaine (et Rust en plus).

Il n'y a pas que la vitesse d’exécution qui compte sinon c'est le langage assembleur qui serait le seul utilisé. Le C a été inventé pour s'affranchir de son bas niveau d'abstraction: le compilateur a traduit le langage C en assembleur. Mais la compilation prend du temps d'où l'intérêt de Python, sans compter que Python est encore de plus haut niveau (proche du langage naturel).

Tant que Python n'est pas rédhibitoire en terme d’exécution (tourne même sur un Raspberry, si, si), il est préférable tant au niveau de l'écriture du code (le plus rapide) que de sa maintenance (le plus concis et lisible).

Dans l'autre cas, rien n'empêche, comme il est dit dans l'article, d'écrire les briques en C/C++/Rust et le ciment en Python. Ou même d'imaginer un tandem avec un programme d'interface écrit en Python s’exécutant un Raspberry et un moteur écrit en C s'exécutant sur un supercalculateur.
3  1 
Avatar de archqt
Membre émérite https://www.developpez.com
Le 29/12/2022 à 18:38
Citation Envoyé par archqt Voir le message
Sinon gros soucis de mémoire sur le code C++

L'héritage ne sert à rien, il suffit juste de mettre un vmax de départ dans le constructeur
Que celui qui moinsse de façon débile ou compulsive explique s'il en a le courage pourquoi d'après lui il n'y a pas de soucis de mémoire, et aussi à quoi sert l'héritage dans ce cas.
4  2