2011-11-09 3 views
14

J'ai quelques fonctions écrites en C pour un projet de jeu. Ces fonctions s'appellent beaucoup (environ 2000-4000 fois par seconde). Les fonctions sont écrites en C pour la vitesse brute. Maintenant, la façon la plus simple d'inclure ces fonctions dans Python est d'utiliser ctypes. L'alternative est d'écrire une extension C vers Python autour de ces fonctions (ce qui demande un peu plus d'effort). Donc, je me demandais, sans compter le chargement initial de la DLL, quelle est la surcharge de ctypes?ctypes vs extension C


J'utilise Python 2.7 (la version standard CPython), et je ne veux pas utiliser une bibliothèque externe comme Cython.

Je sais que cette question a été posée auparavant, mais je n'ai pas vu beaucoup d'informations sur la comparaison des performances entre les deux options.

+0

Eh bien, le JIT de PyPy peut produire un très bon code pour les appels 'ctypes' depuis une version ou deux. Vous voudrez peut-être essayer. Je ne poste pas cela comme une réponse parce que je n'ai pas de données concrètes à portée de main et il n'est pas clair si le changement d'interprète est une option pour vous. – delnan

+0

Je m'attendrais à ce que les frais généraux soient similaires. –

+0

@Delnan: C'est un jeu que je vais expédier - aussi à linux. Je ne peux pas demander à mes utilisateurs d'installer PyPy. – orlp

Répondre

10

J'ai comparé les performances d'une extension C et d'un wrapper ctypes. Dans mon test particulier, la différence était d'environ 250x. Il y avait plusieurs appels dans la bibliothèque C, de sorte que le wrapper ctypes exécutait également du code Python. Le temps d'exécution de la bibliothèque C était très court, ce qui a rendu la surcharge supplémentaire pour le code Python encore plus significative. Donc, le ratio sera probablement différent pour vous mais était significatif dans mon cas.

+5

Alors, lequel était 250x plus lent? – delnan

+1

@delnan: de sa réponse je peux lire l'emballage de ctypes était plus lent. – orlp

6

L'interface codée directement en C peut être beaucoup plus rapide. Le goulot d'étranglement est l'interface de Python vers C et les arguments de regroupement et les résultats peuvent par exemple impliquer la copie de chaînes ou la conversion de listes Python en/à partir de C arrays. Si vous avez une boucle qui fait plusieurs centaines de ces appels et que certaines données n'ont pas à être classées séparément pour chaque appel, tout ce que vous avez à faire est de recoder la boucle en C et vous pourrez peut-être réduire massivement le goulot d'étranglement . ctypes ne vous donne pas cette option: tout ce que vous pouvez faire est d'appeler les fonctions existantes directement.

Bien sûr, tout dépend du type de fonctions que vous appelez et du type de données que vous transmettez. Il se peut que vous ne puissiez pas réduire les frais généraux, auquel cas je m'attendrais toujours à ce que les ctypes soient plus lents mais peut-être pas de manière significative.

Votre meilleur serait de rassembler un échantillon de votre code écrit de chaque façon et de le comparer. Sinon, il y a juste trop de variables pour une réponse définitive.

+0

Les données dont nous parlons sont un masque de bits (pour collision) .J'ai une implémentation C prête, et la seule Les données transmises dans le code Python sont des booléens, des coordonnées et de nouvelles classes de masques binaires python (qui ne contiennent qu'un pointeur vers les données elles-mêmes, qui se trouvent dans le code C.) – orlp