Performance Python – avez-vous déjà eu à réécrire quelque chose d’autre?

Quelqu’un at-il déjà eu du code en Python, qui s’est avéré ne pas fonctionner assez rapidement?

Je veux dire, vous avez été obligé de choisir une autre langue à cause de cela?

Nous étudions l’utilisation de Python pour quelques projets plus importants, et je pense que dans la plupart des cas, Python est suffisamment rapide pour la plupart des scénarios (comparé à Java) car il repose sur des routines C optimisées.

Je voulais voir si les gens avaient des instances où ils avaient démarré en Python, mais ils ont dû aller avec autre chose à cause des performances.

Merci.

Oui j’ai. J’ai écrit un programme de comptage de lignes pour un fichier de sortie bcp binary (préfixé par la longueur plutôt que délimité) et j’ai dû le refaire en C parce que celui de python était trop lent. Ce programme était assez petit (cela ne prenait que quelques jours pour le ré-écrire en C), donc je ne me suis pas donné la peine d’essayer de construire une application hybride (colle python avec des routines centrales écrites en C) mais cela aurait aussi été une voie viable.

Une application plus grande avec des bits critiques de performance peut être écrite en une combinaison de C et d’un langage de niveau supérieur. Vous pouvez écrire les parties critiques de la performance dans C avec une interface vers Python pour le rest du système. SWIG , Pyrex ou Boost.Python (si vous utilisez C ++) fournissent tous de bons mécanismes pour effectuer la plomberie de votre interface Python. L’ API C pour python est plus complexe que celle pour Tcl ou Lua , mais n’est pas infaisable à construire manuellement. Pour un exemple d’une API Python / C construite à la main, consultez cx_Oracle .

Cette approche a été utilisée sur de nombreuses applications réussies remontant aux années 1970 (à ma connaissance). Mozilla était essentiellement écrit en Javascript autour d’un moteur de base écrit en C. Plusieurs logiciels de CAO , Interleaf (un système de publication de documents techniques) et bien sûr EMACS sont essentiellement écrits en LISP avec un langage C, assembleur ou autre. De nombreuses applications commerciales et open-source (par exemple Chandler ou Sungard Front Arena ) utilisent des interpréteurs Python intégrés et implémentent des parties substantielles de l’application en Python.

EDIT: En réponse au commentaire de Dutch Masters, garder une personne avec des compétences en programmation C ou C ++ dans l’équipe pour un projet Python vous donne la possibilité d’écrire une partie de l’application pour la vitesse. Les domaines dans lesquels vous pouvez vous attendre à un gain de performance significatif sont ceux où l’application fait quelque chose de très itératif sur une structure de données volumineuse ou un volume de données important. Dans le cas du compteur de lignes ci-dessus, il devait inhaler une série de fichiers totalisant plusieurs gigaoctets et passer par un processus où il lisait un préfixe de longueur variable et l’utilisait pour déterminer la longueur du champ de données. La plupart des champs étaient courts (quelques octets de long). C’était un peu bizarre et très bas et itératif, ce qui en faisait un choix naturel pour C.

Beaucoup de bibliothèques python telles que numpy , cElementTree ou cSsortingngIO utilisent un kernel C optimisé avec une API python qui facilite le travail avec les données de manière agrégée. Par exemple, numpy a des structures de données masortingcielles et des opérations écrites en C qui font tout le travail et une API Python qui fournit des services au niveau agrégé.

C’est une question beaucoup plus difficile à répondre que les gens sont prêts à admettre.

Par exemple, il se peut que je puisse écrire un programme plus performant en Python qu’en C. La conclusion fallacieuse de cette déclaration est que “Python est donc plus rapide que C”. En réalité, cela peut être dû à mon expérience beaucoup plus récente en Python et ses meilleures pratiques et bibliothèques standard.

En fait, personne ne peut vraiment répondre à votre question à moins d’être certain de pouvoir créer une solution optimale dans les deux langues, ce qui est peu probable. En d’autres termes, “ma solution C était plus rapide que ma solution Python” n’est pas la même chose que “C est plus rapide que Python”

Je suis prêt à parier que Guido Van Rossum aurait pu écrire des solutions Python pour les problèmes d’Adam et de Dustin qui ont très bien fonctionné.

Ma règle de base est que, sauf si vous écrivez le type d’application qui vous oblige à compter les cycles d’horloge, vous pouvez probablement obtenir des performances acceptables en Python.

Ajouter mes 0,02 $ pour l’enregistrement.

Mon travail consiste à développer des modèles numériques exécutant plus de 100 gigaoctets de données. Les problèmes sont de trouver rapidement une solution générasortingce de revenus (c.-à-d. Le temps de mise sur le marché). Pour réussir commercialement, la solution doit également s’exécuter rapidement (calcul de la solution dans un délai minimal).

Pour nous, Python s’est avéré un excellent choix pour développer des solutions pour les raisons les plus fréquemment citées: temps de développement rapide, expressivité linguistique, bibliothèques riches, etc. Mais pour répondre aux besoins de rapidité d’exécution, nous avons adopté l’approche hybride. ont déjà mentionné.

  1. Utiliser numpy pour les parties à calcul intense. Nous obtenons entre 1,1 et 2,5 fois la vitesse d’une solution C ++ «native» avec numpy avec moins de code, moins de bogues et des temps de développement plus courts.
  2. Pickling (sérialisation d’object Python) résultats intermédiaires pour minimiser le nouveau calcul. La nature de notre système nécessite plusieurs étapes sur les mêmes données. Nous mémorisons donc les résultats et les réutilisons dans la mesure du possible.
  3. Profilage et choix de meilleurs algorithmes. Cela a été dit dans d’autres réponses, mais je le répète: nous découvrons cProfile et essayons de remplacer les points chauds par un meilleur algorithme. Non applicable dans tous les cas.
  4. Aller en C ++. Si ce qui précède échoue, nous appelons une bibliothèque C ++. Nous utilisons PyBindGen pour écrire nos wrappers Python / C ++. Nous l’avons trouvé bien supérieur à SWIG, SIP et Boost.Python, car il produit directement du code API Python C sans couche intermédiaire.

En lisant cette liste, vous pourriez penser “Quel travail de remaniement! Je le ferai simplement en [C / C ++ / Java / Assembleur] la première fois et finis-en.”

Laissez-moi le mettre en perspective. En utilisant Python, nous avons pu produire une application générasortingce de revenus en 5 semaines qui, dans d’autres langues, nécessitait auparavant 3 mois pour des projets de scope similaire. Cela inclut le temps nécessaire pour optimiser les composants Python que nous avons trouvés lents.

Pendant que chez uni nous écrivions un système de vision par ordinateur pour parsingr le comportement humain basé sur des clips vidéo. Grâce à l’excellent PIL, nous avons utilisé python pour accélérer le développement et accéder facilement aux images que nous avions extraites de la vidéo pour les convertir en tableaux, etc.

Pour 90% de ce que nous voulions, c’était bien et comme les images étaient d’une résolution relativement basse, la vitesse n’était pas mauvaise. Cependant, quelques-uns des processus ont nécessité des calculs complexes pixel par pixel ainsi que des convolutions notoirement lentes. Pour ces zones particulières, nous avons réécrit les parties les plus internes des boucles en C et nous avons simplement mis à jour les anciennes fonctions Python pour appeler les fonctions C.

Cela nous a donné le meilleur des deux mondes. Nous avons eu la facilité d’access aux données que Python fournit, ce qui a permis de développer rapidement, puis la vitesse linéaire de C pour les calculs les plus intensifs.

Pas si loin. Je travaille pour une entreprise qui dispose d’un moteur de simulation moléculaire et d’un ensemble de programmes écrits en python pour traiter les grands ensembles de données multi-gigaoctets. Tous nos logiciels d’parsing sont en cours d’écriture en Python en raison des énormes avantages de la flexibilité et du temps de développement.

Si quelque chose n’est pas assez rapide, nous le profilons avec cProfile et trouvons les goulots d’étranglement. Il y a généralement une ou deux fonctions qui occupent 80 ou 90% du temps d’exécution. Nous prenons ensuite ces fonctions et les réécrivons dans C, ce que Python rend facile avec son API C. Dans de nombreux cas, cela se traduit par un ordre de grandeur ou plus rapide. Problème disparu Nous continuons ensuite notre chemin joyeux en continuant à écrire tout le rest en Python. Rincer et répéter …

Pour des modules ou des classes entiers, nous avons tendance à utiliser Boost.python, cela peut être un peu difficile, mais au final, cela fonctionne bien. Si c’est juste une fonction ou deux, nous l’incluons parfois avec scipy.weave si le projet utilise déjà scipy.

Chaque fois que je trouve un goulot d’étranglement Python, je réécris ce code en C en tant que module Python.

Par exemple, j’ai du matériel qui envoie des pixels d’image en tant que 0RGB à 4 octets. La conversion de 8 Mo de 0RGB à RGB en Python prend trop de temps, alors je l’ai réécrit en tant que module Python.

L’écriture de Python (ou d’autres langages de niveau supérieur) est beaucoup plus rapide que l’écriture en C, donc j’utilise Python jusqu’à ce que je ne puisse pas.

Ce genre de question est susceptible de déclencher une guerre religieuse entre les personnes de langue alors laissez-moi répondre un peu différemment.

Dans la plupart des cas, dans les environnements informatiques actuels, votre choix de langage de programmation doit être basé sur ce que vous pouvez programmer efficacement, bien programmer et ce qui vous rend heureux, et non les caractéristiques de performance du langage. En outre, l’optimisation devrait généralement être la dernière préoccupation lors de la programmation de tout système.

La manière la plus courante de faire les choses en python est de commencer à écrire votre programme en python, puis, si vous remarquez que les performances en souffre, essayez d’abord d’utiliser les points chauds de Python. Si l’optimisation du code python n’est toujours pas suffisante, les zones du code qui vous pèsent devraient être réécrites en tant que module Python en C. Si même après tout cela votre programme n’est pas assez rapide, vous pouvez soit changer langues ou regarder la mise à l’échelle dans le matériel ou la concurrence.

C’est la longue réponse, pour répondre directement à votre question; Non, python (parfois avec des extensions C) a été assez rapide pour tout ce dont j’ai besoin. Le seul moment où je me penche vraiment sur C est d’avoir access à des éléments qui n’ont pas de liens python.

Edit: Mon arrière-plan est un programmeur de python sur un grand .com où nous utilisons python pour tout, depuis le front-end de nos sites Web jusqu’à tous les systèmes de back-office. Python est un langage d’entreprise.

Bien que l’implémentation d’un serveur memcache spécialisé pour un certain type de données, le backend de stockage serait plus efficace en termes de mémoire et le temps de recherche pourrait être réduit par des opérations de recherche sur les bits (par exemple: recherches O (1) ).

J’ai écrit toute la partie implémentation du protocole et du démon événementiel avec Python en deux jours, ce qui nous a permis de tester les fonctionnalités et de nous concentrer sur les performances pendant que l’équipe validait la conformité du protocole et les autres bits.

Etant donné les outils comme Pyrex , l’implémentation des extensions C pour Python est presque banale pour tout développeur expérimenté en C. J’ai réécrit le backend de stockage basé sur Radix Tree en C et en ai fait un jour avec Pyrex. L’utilisation de la mémoire pour les préfixes 475K est passée de 90 Mo à 8 Mo. Nous avons obtenu un saut de 1200% dans les performances de la requête.

Aujourd’hui, cette application s’exécute avec pyevent (interface Python pour libevent) et le nouveau serveur de stockage gère 8 000 requêtes par seconde sur un serveur simple cœur, fonctionnant comme un démon de processus unique (grâce à libevent) consommant moins de 40 Mo de mémoire . l’interpréteur Python) tout en gérant 300+ connexions simultanées.

C’est un projet conçu et mis en œuvre pour la qualité de la production en moins de 5 jours. Sans Python et Pyrex, cela prendrait plus de temps.

Nous aurions pu résoudre le problème de performance en utilisant simplement des serveurs plus puissants et en basculant vers un modèle multi-processus / multi-instance tout en compliquant les tâches de code et d’administration, avec une empreinte mémoire beaucoup plus importante.

Je pense que vous êtes sur la bonne voie pour aller avec Python.

J’avais l’habitude de prototyper beaucoup de choses en python pour faire des choses comme le traitement des journaux. Quand ils ne couraient pas assez vite, je les réécrivais dans ocaml.

Dans de nombreux cas, le python allait bien et j’en étais heureux. Dans certains cas, à l’approche des 23 heures de journalisation, je pouvais réécrire. 🙂

Je voudrais souligner que même dans ces cas, il aurait été préférable de simplement profiler le code python et de trouver une implémentation Python plus heureuse.

Vous pouvez toujours écrire des parties de votre application en Python. Tous les composants ne sont pas aussi importants pour la performance. Python s’intègre facilement avec C ++ en mode natif, ou avec Java via Jython, ou avec .NET via IronPython.

Au fait, IronPython est plus efficace que l’implémentation C de Python sur certains tests.

Je travaille depuis un certain temps, développant une application qui fonctionne sur de grandes données structurées, stockées dans des bases de données de plusieurs gigaoctets et, bien, Python est assez bon pour cela. L’application dispose d’un client GUI avec une multitude de contrôles (listes, arborescences, blocs-notes, listes virtuelles, etc.) et un serveur de console.

Nous avions quelques problèmes de performances, mais ceux-ci étaient principalement liés à une mauvaise conception des algorithmes ou à des limitations du moteur de firebase database (Oracle, MS-SQL, MySQL et BerkeleyDB utilisés pour les optimisations de vitesse). Une fois que vous savez comment utiliser correctement les bibliothèques standard (écrites en C), vous pouvez rendre votre code très rapide.

Comme d’autres disent – tout algorithme de calcul intensif, le code qui dépend du bourrage de bits, un calcul limité par la mémoire – peut être fait en C / C ++ brut pour l’économie de CPU / mémoire (ou toute autre astuce), mais la gestion des bases de données, la gestion des erreurs – tout ce qui rend l’application réellement exécutée, peut être écrite en Python et elle conservera une réactivité et des performances globales décentes.

Je développe en python depuis plusieurs années maintenant. Récemment, j’ai dû répertorier tous les fichiers d’un répertoire et créer une structure avec le nom de fichier, la taille, les atsortingbuts et la date de modification. Je l’ai fait avec os.listdir et os.stat . Le code était assez rapide, mais plus il y avait d’entrées dans les répertoires, plus mon code devenait lent à d’autres gestionnaires de fichiers listant le même répertoire, donc j’ai réécrit le code avec SWIG / C ++ et j’ai été vraiment surpris.

Oui, deux fois:

  • Une application audio DSP que j’ai fini par réécrire complètement en C ++ car je ne pouvais pas obtenir les performances appropriées en Python; Je ne considère pas l’implémentation de Python comme un gaspillage, car cela me permet de prototyper le concept très facilement, et le port C ++ s’est bien passé car j’avais une implémentation de référence de travail.

  • Un projet de rendu graphique procédural, où la génération de grandes cartes de texture 2D en Python prenait beaucoup de temps; J’ai écrit une DLL C ++ et utilisé ctypes / windll pour l’utiliser depuis Python.

Non, je n’ai jamais eu à réécrire. En fait, j’ai commencé à utiliser Python dans Maya 8.5. Avant Maya 8, le seul langage de script disponible était le MEL (Maya Expression Language) intégré. Python est en fait plus rapide que le langage intégré qu’il encapsule.

La capacité de Python à travailler avec des types de données complexes a également accéléré le processus, car MEL ne peut stocker que des tableaux à une dimension (et aucun pointeur). Cela nécessiterait de truquer les tableaux multidimensionnels soit en utilisant plusieurs tableaux parallèles, soit en utilisant une concaténation de chaînes lente.

Il y a un mois, j’ai eu ce petit programme écrit en Python (pour le travail) qui parsing les journaux. Lorsque le nombre de fichiers journaux a augmenté, le programme a commencé à être très lent et je pensais pouvoir le réécrire en Java.

J’étais très intéressant. Il a fallu une journée entière pour migrer le même algorithme de Python vers Java. En fin de compte, quelques essais comparatifs ont montré clairement que le programme Java était 20% / 25% plus lent que son homologue Python. Ce fut une surprise pour moi.

En écrivant pour la deuxième fois, l’algorithme m’a également montré qu’une certaine optimisation était possible. Donc, en deux heures, j’ai complètement réécrit le tout en Python et il était 40% plus rapide que l’implémentation Python originale (donc des temps plus rapides que la version Java que j’avais).

Alors:

  1. Python est un langage lent mais il peut toujours être plus rapide, pour certaines tâches, que d’autres langages supposés plus rapides

  2. Si vous devez passer du temps à écrire quelque chose dans un langage dont l’exécution est plus rapide mais dont le temps de développement est plus lent (la plupart des langues), envisagez d’utiliser le même temps pour parsingr le problème, rechercher des bibliothèques, créer un profil et écrire un meilleur code Python.

J’ai dû écrire un générateur de nombres pseudo-aléatoires pour un simulateur. Je l’ai d’abord écrit en Python, mais Python s’est avéré trop lent. J’ai fini par le réécrire en C, et même cela a été lent, mais pas aussi lent que Python.

Heureusement, il est assez facile de relier Python et C, alors j’ai pu écrire le PRNG en tant que module C et écrire le rest du simulateur en Python.

Le lien suivant fournit une comparaison continue entre plusieurs langages informatiques. Cela devrait vous donner une idée de certaines des forces et faiblesses de Python dans différents domaines de problèmes.

Jeu de tests de langage informatique

Je suis en train de réécrire le programme Perl OpenKore en Python sous le nom d’ Erok (inverse du Kore original). Jusqu’à présent, Python s’est révélé être un meilleur langage, en particulier grâce à ses puissantes fonctions d’parsing de chaînes qui ne nécessitent pas l’utilisation d’expressions régulières, ce qui accélère vraiment beaucoup son parsing de fichiers.

Je ne réécris généralement pas à C avant que je:

  • profil
  • réécrire avec des algorithmes bette (généralement cela suffit)
  • réécrire le code python en gardant à l’esprit les performances de bas niveau (mais jamais au point d’avoir du code non pythonique / non lisible)
  • passer du temps à revérifier qu’une bibliothèque ne peut pas faire cela (d’abord dans stdlib, ou une lib externe)
  • essayé psyco / autres implémentations (obtient rarement une augmentation de vitesse réelle dans mon cas)

Puis, parfois, j’ai créé une bibliothèque partagée pour faire du code de calcul de masortingce lourde (ce qui ne pouvait pas être fait avec numarray) et l’a appelé avec des ctypes:

  • simple pour écrire / construire / tester un .so / dll dans pure C,
  • simple d’encapsuler la fonction C to python (c.-à-d. que vous n’utilisez pas les types de données de base puisque les ctypes font tout le travail d’appeler les bons arguments pour vous) et certainement assez rapidement.