J'ai une compétition amicale avec quelques gars dans le domaine de la programmation et récemment, nous sommes devenus si intéressés par l'écriture de code efficace. Notre défi consistait à essayer d'optimiser le code (en sens du temps et de la complexité du processeur) à tout coût (lisibilité, réutilisabilité, etc.). P>
Le problème est que nous devons maintenant comparer nos codes et voir quelle approche est mieux comparable aux autres, mais nous ne connaissons aucun outil à cet effet. P>
Ma question est, existe-t-il des outils (n'importe où!) qui prend un code de code En tant qu'entrée et calcule le nombre de flops ou des instructions de la CPU nécessaire pour le faire fonctionner? Y a-t-il un outil peut mesurer l'optimisation d'un code? p> blockQuote>
P.s. La langue cible est C ++ mais serait agréable de savoir si ces outils existent également pour Java. P>
7 Réponses :
Il est assez difficile de calculer le nombre de détails de la durée de la CPU à partir d'un bloc de code. La manière habituelle de le faire est de concevoir les données d'entrée pires / moyennes / meilleures comme cas de test. Et faire un profilage de synchronisation basé sur votre code réel avec ces cas de test. Il n'existe aucun outil ne peut vous dire les flops lorsqu'il est sans les données et conditions de test de saisie. p>
Voici un petit chronomètre C ++ 11 J'aime déployer quand j'ai besoin de faire du temps quelque chose: utilisation: p> Sur toute implémentation décente, le high_resolution_clock par défaut code> devrait donner des informations de synchronisation très précises. P> p>
Sur Visual Studio High_Resolution_Clock CODE> est horrible, utilisez la version Bibliothèques de boost dans ce cas.
@ronag: Merci pour les conseils!
+1: Le timing est généralement meilleur que le profilage lorsqu'il s'agit de déterminer quel morceau de code est plus rapide. Le profilage manque généralement les effets de mise en cache et similaires qui peuvent avoir un effet énorme sur la performance.
Pour le calendrier à haute résolution, vous devez utiliser directement les appels système appropriés, tels que Clock_GetTime () sur Linux, qui fournit une résolution de nanoseconde réelle. Les pénalités des appels chrono pourraient causer trop de gigue / autres effets négatifs. L'appel du système Clock_GetTime () prend plusieurs centaines de tiques CPU pour fonctionner, mais la durée semble assez constante. Si vous souhaitez PERFAIRE I> TIMING, puis désactivez le gouverneur de fréquence de la CPU de votre système d'exploitation et comptez les ticks de la CPU réels avec l'instruction de l'assemblage du processeur (telle que RDTSC).
@Mic_E: Le problème avec TSC est qu'il ne joue pas bien avec plusieurs cœurs. L'horloge stable fournie par chrono code> ou
clock_gettime code>, surmonte ceci.
Pourquoi est-ce si compliqué? Comment est-ce que c'est mieux que d'utiliser std :: chrono :: high_resolution_clock :: maintenant (); code> avant et après la fonction est appelée et soustrayant la différence?
@ Northerner: Si vous avez juste besoin de le faire une fois, alors, alors sûr, mais une petite solution de bibliothèque comme celle-ci apporte une utilisation répétée d'un peu moins encombré.
Bon ! Mais pourquoi reporter_ms renvoie non signé long long long int code> au lieu de double? BTW, je n'ai pas entendu parler de
non signé longtemps long int code> tel type.
@Lewischan: Je pense que c'est parce que le modèle principal renvoie un compte typiquement intégrant, et la spécialisation fait donc la même chose.
Il y a la fonction std :: horloge () code> de la fonction
std :: horlecks_per_sec code> (également à partir de
Il y a des logiciels appelés Profilers qui font exactement ce que vous voulez. p>
Un exemple pour Windows est analyseur de code AMD et GProf pour POSIX. P>
Le problème avec le profilage de juger des concours de performance est que l'acte de profilage lui-même ralentit l'exécution du programme. Certains algorithmes pourraient être affectés plus que d'autres, ce qui oblige les résultats de la concurrence. De plus, la compilation avec le support de profilage empêche certaines optimisations de compilateur pouvant être utilisées pour épermettre le dernier morceau de vitesse supplémentaire. Ne vous méprenez pas: les profileurs sont des outils importants pour trouver des goulots d'étranglement performants. Mais vous ne devriez pas leur faire confiance aveuglément.
@Philipp je ne fais pas confiance aux profileurs aveuglément, je ne suis pas ce type de mec de mathématiques. Je pensais que cela aurait été une bonne idée de les mentionner comme il me semblait que OP ne le savait pas du tout.
@Philipp n'est pas non plus je vois pourquoi cette réponse devrait-elle être évitée - elle est techniquement correcte ...
Encore une fois, s'il vous plaît laissez un commentaire si vous avez downvote avec votre raisonnement précis! B>
Mesurer le nombre d'instructions de la CPU est assez inutile. P>
performance est relatif au goulot d'étranglement, en fonction du problème à la main, le goulot d'étranglement peut être le réseau, le disque iOS, la mémoire ou la CPU. P>
Pour juste une compétition amicale, je suggérerais de timing. Qui implique de fournir des cas de test suffisamment importants pour avoir des mesures significatives, bien sûr. P>
sur UNIX, vous pouvez utiliser GetTimeofday code> pour des mesures relativement précises. P>
à partir de l'assemblage en ligne, vous pouvez utiliser des instructions RDTSC pour obtenir un compteur 32 bits (une partie la moins importante) dans EAX et 32 bits (partie la plus élevée significative) à EDX. Si votre code est trop petit, vous pouvez vérifier les cycles CPU totaux appropriés avec Just EAx Register. Si le nombre est supérieur à max. de Valeur 32 bits, ADX incréments par cycle de valeur max-32 bits.
int cpu_clk1a=0; int cpu_clk1b=0; int cpu_clk2a=0; int cpu_clk2b=0; int max=0; std::cin>>max; //loop limit __asm { push eax push edx rdtsc //gets current cpu-clock-counter into eax&edx mov [cpu_clk1a],eax mov [cpu_clk1b],edx pop edx pop eax } long temp=0; for(int i=0;i<max;i++) { temp+=clock();//needed to defy optimization to actually measure something //even the smartest compiler cannot know what //the clock would be } __asm { push eax push edx rdtsc //gets current cpu-clock-counter into aex&edx mov [cpu_clk2a],eax mov [cpu_clk2b],edx pop edx pop eax } std::cout<<(cpu_clk2a-cpu_clk1a)<<std::endl; //if your loop takes more than ~2billions of cpu-clocks, use cpu_clk1b and 2b getchar(); getchar();
+1 pour le mot "optimisme". Est-ce suffisant pour exécuter
temps ./prog code>?
@Kerreksb je crois que OP veut un profileur.
Je ne pense pas que les flops ou les instructions de la CPU sont une bonne mesure d'efficacité. Il est facile de gifler le code artificiel de ne-rien de ne peut-il pas supporter. a>