J'ai à peu près le même code dans Python et C. EXEMPLE PYTHON:
$ time python numpy_test.py real 0m5.967s user 0m5.932s sys 0m0.012s $ g++ sin.c $ time ./a.out real 0m13.371s user 0m13.301s sys 0m0.008s
3 Réponses :
Tout d'abord, activez l'optimisation. Deuxièmement, les subtilités comptent. Votre code C n'est définitivement pas «fondamentalement le même».
Voici Code C équivalent: P>
Sarary2.c: P>
$ time python foo.py real 0m5.986s user 0m5.783s sys 0m0.050s $ gcc -O3 -ffast-math sinary.c sinary2.c -lm $ time ./a.out real 0m5.204s user 0m4.995s sys 0m0.208s
Je pense qu'il serait instructif de comprendre quelles fonctionnalités en particulier rendent le code C original tellement plus lent que votre version.
@NPE - Je pense que c'est en fait juste l'optimiseur. Presque tout le reste que j'ai fait aurait probablement fait ralentir le code. :-) Je vais vérifier cependant. Oui, certainement l'optimiseur est ce qui l'a fait. Sans l'optimiseur, mon code est beaucoup plus lent.
Si nous éliminons la différence de type de données (sur ma boîte, il n'a que peu d'effet sur la performance), il n'est pas déraisonnable de s'attendre à ce que Sinf () code> soit le coût dominant. Pourtant, il y a quelque chose sur le code de l'OP qui est très coûteux. En regardant la source et le démontage, ce n'est pas évident pour moi ce que cela pourrait être ...
@NPE: C'est une question délicate. Étant donné que l'optimiseur fera une viande de chauffage du code d'origine OPS. Je suppose que le code de maintenance en boucle est ce qui prend le temps. Je pense que le seul moyen de dire est de regarder la production de montage et de faire des suppositions éduquées. C'est en fait la fonctionnalité principale b> qui rend UN NUMPY FAST est qu'il déplace tout le code de maintenance en boucle en C.
Je ne sais pas si -ffast-math code> est juste ici. Je pense que je me souviens de quelque chose dans le dos de mon esprit que Fast-Math Code> Sacrifications Precision pour la vitesse, quels numpy ne le fait sûrement pas.
@ US2012: Cela ne sacrifie pas la précision du sens ordinaire. Il sacrifie délibérément perd la précision pour satisfaire aux exigences de la rapidité des normes IEEE. Et je viens de vérifier et le temps sans -ffast-math code> est à peu près le même, peut-être même un peu moins.
Je viens de courir oprofile sur le code d'origine telle que fournie ci-dessus (avec un printf ("% f \ n", x) code> à la fin) et dépense environ 65% du temps dans "péché" .
@MatSpetersson: avec ou sans optimisation? :-)
Avec optimisation (-O3 -SSE2 -FAST-MATH) - Sinon, je m'attends à ce que ce soit nettement moins de temps total.
Je suis vraiment curieux à propos de celui-ci, donc j'ai posté une question séparée: Stackoverflow.com/questions/14468639/...
Parce que "NUMPY" est une bibliothèque de mathématiques dédiée mise en œuvre pour la vitesse. C a des fonctions standard pour SIN / COS, qui sont généralement dérivées pour la précision. p>
Vous ne comparez pas non plus de pommes avec des pommes, car vous utilisez Double en C et Float32 (flotteur) en Python. Si nous changeons le code Python pour calculer Flat64 à la place, le temps augmente d'environ 2,5 secondes sur ma machine, ce qui le rendra à peu près à la version C correctement optimisée. p>
Si tout le test a été fait pour faire quelque chose de plus compliqué qui nécessite plus de structes de contrôle (si / bienfait, do / tandis que, etc.), vous verriez probablement moins de différence entre C et Python - parce que le compilateur C peut " t vraiment "péché" tout plus rapidement - sauf si vous implémentez une meilleure fonction "sin". p>
Mind plus récent Le fait que votre code n'est pas tout à fait pareil des deux côtés ...;) p>
Je me demande si le péché de Numpy est même correct. La plupart des implémentations de Trigs «optimisées» ont une réduction de l'argumentation horriblement fausse.
Vous semblez faire la même opération en C 8192 x 10000 fois, mais seulement 10000 en Python (je n'ai pas utilisé NUMPY auparavant afin que je puisse mal comprendre le code). Pourquoi utilisez-vous un tableau dans le boîtier Python (encore une fois, je ne suis pas utile à NUMPY, donc peut-être que la déséroférance est implicite). Si vous souhaitez utiliser un tableau Soyez prudent Doubles, ayez une performance touchée en termes de mise en cache et d'optimisation vectorisée - vous utilisez différents types entre les deux implémentations (float vs double), mais étant donné l'algorithme que je ne pense pas que cela compte. p>
La principale raison de beaucoup de problèmes de référence de performance anormale entourant C vs Pythis, pythat ... est que simplement la mise en œuvre C est souvent médiocre. P>
Si vous remarquez que le gars écrit C pour traiter un tableau de doubles (sans utiliser de mots-clés restreindre ou const où il aurait pu), il construit avec optimisation puis oblige le compilateur à utiliser SIMD plutôt que possible. En bref, le compilateur utilise un ensemble d'instructions inefficaces pour les doubles et le mauvais type de registres également s'il souhaite une performance - vous pouvez être sûr que le numba et les numéros utiliseront autant de cloches et de sifflets que possible et seront expédiés avec des C très efficaces. et des bibliothèques C ++ pour commencer. En bref si vous voulez une vitesse avec C, vous devez y penser, vous pouvez même devoir démonter le code et peut-être désactiver l'optimisation et utiliser des instrumentsiques de compilateur à la place. Cela vous donne les outils pour le faire, vous ne vous attendez pas à ce que le compilateur fasse tout le travail pour vous. Si vous voulez que le degré de liberté utilise Cython, Numba, Numpy, Sciped, etc. Ils sont très rapides, mais vous ne pourrez pas éponger chaque performance de la machine - à faire cet usage C, C ++ ou neuf versions de Fortran. P>
Voici un très bon article sur ces points mêmes (j'utiliserais Scipy): P>
Avez-vous compilé votre code C avec des optimisations? (
-O2 code> ou-O3 code>)On dirait que non. Essayez
GCC -O2 A.C CODE>Je crois que
-O2 code> ne coupe pas, essayezgcc -o2 -ftree-vectorize -msse2 a.c code>Ce n'est pas le cas «fondamentalement le même code» non plus.
Avec -O3 La version C est environ 18000 fois plus rapide sur ma machine - probablement parce qu'il optimise toutes les boucles ...;)
@MatSpetersson, oui, il faut probablement ajouter un
printf ("% lf \ n", x); code> à la fin pour éviter cela. :)@MATSPETERSSON Oui, il supprime entièrement la boucle, cela se produit déjà avec
-o code> sur ma machine.@ Phan0M: Donc, il coule le même code sur et plus de 8192 fois?
Si vous avez un processeur multi-enseignements, essayez également de compiler C Programme avec OpenMP et d'écrire avant le premier cycle:
#pragma oomp parallèle pour code> et#define omp_num_threads n code> où n est environ un .. une et la moitié de votre nombre de noyaux.@szx Non, il ne configure que la valeur de retour de
principal () code> et sort, jamais même appelersin code>.Merci pour des réponses. Maintenant, il y a environ 2,5 secondes, comme je m'y attendais.
Après avoir imprimé la valeur de X, je reçois la différence 1S entre Python et C-C étant la plus lente.
@ Phant0m attend quoi? Alors, comment obtient-il la "bonne" réponse?
@PinkelephantsonParade: la réponse est connue à l'heure de la compilation:
retour 0 code>.@PinkelepantsonParade sans la déclaration d'impression, il n'a pas besoin d'informer quoi que ce soit, car la valeur n'est jamais réellement utilisée.
@HONK AH ... je vois. C'est assez drôle, lol.
Je pense que c'est une question intéressante et instructive. Voter à re-ouvert.
@NPE: Je suis d'accord, je ne sais pas pourquoi c'était fermé.
Et si vous déclarez X comme un flotteur (au lieu d'un double) et utilisez X = Sinf (x). Alors quelle est votre vitesse?