J'ai essayé 2 choses: (pseudo code ci-dessous) et p> J'ai exécuté à la fois les programmes et l'a programmé en utilisant le Commande "Time" Shell. Le programme 1 fonctionne en 5 secondes, le programme 2 est exécuté en 30 secondes. J'ai exécuté les deux programmes avec optimisation du compilateur activé et les deux programmes ont couru à peu près au même moment (0,38s). Je suis confus par ces résultats. Quelqu'un peut-il vous expliquer pourquoi cela se passe-t-il? P> Merci! P> P>
6 Réponses :
Pour le modèle, l'inscription est effectuée avec l'opérateur []. Avec l'optimisation éteinte, cela sera généralement généré comme un appel de fonction réel, ajoutant beaucoup de frais généraux à quelque chose de simple que sous-dominant dans un tableau. Lorsque vous activez l'optimisation, il est généré en ligne, en supprimant cette surcharge. P>
Hey Jerry, merci de votre réponse. Cela a du sens maintenant. Je suppose que avec des tableaux, en utilisant [] n'appelle pas l'appel à l'opérateur [] puisqu'un «naturel» (pour un manque de meilleur mot). D'où le 5/30.
Droite - Pour un tableau intégré, le code d'inscription est presque certainement toujours i> généré en ligne.
Et cela souligne la manière dont les frais de fonction peuvent vraiment s'additionner.
@ AIP.CD.AISH: Les mots "intrinsèques" et "natifs" sont utilisés plus couramment que "naturel" pour décrire les caractéristiques intégrées dans une langue.
@Adisak: Cool, merci. Bon à savoir :)
En mode de débogage, implémentations de std :: vecteur code> fournit beaucoup de vérification de la facilité d'utilisation. Cette vérification n'est pas disponible pour les tableaux natifs. Par exemple, dans VC2008, si vous compilez votre exemple de vecteur code> dans le mode de débogage, il y aura
la vérification de la plage code> même em> dans le cas du
opérateur [] code>. p>
Si votre implémentation vectorielle non optimisée effectue une vérification des limites, cela expliquerait la divergence. P>
++ Mon hypothèse est que vous avez raison, mais je le voulais (ou elle) de le découvrir.
parce que lorsque vous écrivez vectoriel Arr (10000); Vous créez un objet, appelez ses fonctions ... quand et il sera plus lent que vous créez INTRA [10000]; P>
Dans vos exemples, le tableau est sur la pile. L'accès aux données dans le tableau consiste à accéder aux données sur la pile. C'est vite.
D'autre part, tandis que le vecteur code> code> est sur la pile, les données d'un Vous obtenez quelque chose pour la pénalité de performance, cependant. std :: vecteur code> est allouée ailleurs (par défaut, il est attribué Sur le tas via
std :: allocator code>). L'accès à des données dans le vecteur code> code> implique d'accéder aux données sur le tas. C'est beaucoup plus lent que d'accéder à des données sur la pile. P>
std :: vecteur code> est griffable, tandis qu'une matrice régulière n'est pas. De plus, la taille d'un
std :: vecteur code> ne doit pas nécessairement compiler la constante de temps, tandis que la taille d'un tableau sur la pile est. Un tableau alloué en tas (via
opérateur nouveau [] code>) ne doit pas nécessairement être une constante de la compilation. Si vous comparez un tableau alloué en tas avec un
std :: vecteur code> Vous trouverez que la performance est beaucoup plus proche. P>
Ce sont de bonnes réponses, mais il y a un moyen rapide que vous puissiez découvrir pour vous-même. p>
Vous voyez une différence de performance de 6 à 1? Il suffit d'exécuter le lent et appuyez sur le bouton "Pause". Ensuite, regardez la pile d'appels. La probabilité est de 5 sur 6 (83%) que vous verrez exactement comment il dépense ces 25 secondes supplémentaires. Faites-le plusieurs fois pour obtenir autant d'idées que vous le souhaitez. P>
Pour le cas optimisé, faites de même avec le programme 1. Étant donné qu'il est 13 fois plus lent que le programme optimisé, vous verrez la raison pour laquelle sur chaque "pause", avec probabilité 12/13 = 92%. P >
C'est une application de cette technique . p>
J'ai vu de nombreux développeurs qui a soufflé lors de la première vue sur la bonne technique de pause Ole ', surtout quand ils ne l'achètent pas et dépenseront une autre heure serveur de régler une course de profilage complet uniquement pour découvrir "pause" l'avaient déjà cloué.
@Dano: Ouais. J'essaie juste d'obtenir le mot. Il n'y a aucune raison pour que les gens ne le connaissent pas.
Hey Mike, merci pour la réponse. J'aimerais essayer, mais j'utilise un environnement de ligne de commande et GCC pour compiler mes programmes (je suis nouveau dans cet environnement). Y a-t-il de ce que je peux la mettre en pause et voir la trace de la pile là-bas? Merci :)
@ AIP.CD.AISH: J'aimerais que ce soit facile. Fondamentalement, vous devez être utile avec GDB. Ensuite, configurez-la de sorte que le contrôle-c secrété l'interrompt, mais ne l'abandonne pas. Franchement, sous une boîte DOS dans Windows XP, je n'ai pas réussi, si surtout j'utilise VC & vs. Sous UNIX, j'avais l'habitude d'utiliser ADB et je l'envoie un signal de tuer de l'extérieur. J'ai demandé si s'il y a une meilleure façon, mais pas vraiment une bonne réponse.
... Il y a une façon maladroite que j'ai parfois utilisé. Écrivez une fonction vide FOO () {} et saupoudrez des appels sur tout le code. Mettez un point d'arrêt dedans et désactivez cela. Ensuite, quand il fonctionne, voyez si vous pouvez activer le point d'arrêt à un moment aléatoire. Cette méthode n'est pas aussi précise, mais mieux que rien.
... Il y a une autre façon qui pourrait fonctionner dans votre cas. Dans GDB, une seule étape au niveau de l'instruction "SI". Vous verrez exactement ce que ça fait (bien que vous ne l'aimez peut-être pas :).
@Dano: On me rappelle une histoire d'Edison, où il interviewait des ingénieurs. Il leur a demandé de trouver le volume d'un globe d'ampoule. La plupart d'entre eux se sont fixés pour travailler avec calcul et géométrie. On vient de le remplir d'eau et versé dans une tasse à mesurer!
@ AIP.CD.AISH: Utilisez Explorateur de processus de Sysinternals / TechNet, sur la page Process Propriétés | Tabure de threads, choisissez un fil et appuyez sur le bouton de la pile. Vous recevez un instantané lorsque vous avez poussé le bouton. Regardez ce qui est sur le dessus de la fermeture et la remontant à nouveau, vous pouvez facilement obtenir un nouvel échantillon presque chaque seconde. Bien sûr sans mettre en place des symboles, vous obtenez uniquement des compensations. Mais vous pouvez également voir dans les DLL du système de cette façon.
@Dano: Je n'étais pas au courant de l'explorateur de processus, merci. C'est bien que vous puissiez voir dans des dlls système, mais ce que je cherche, c'est des appels de pile mi-pile en code que j'ai le contrôle. Exemple: Stackoverflow.com/ Questions / 406760 / ...
Voulez-vous dire qu'ils ont pris 5/30 secondes avec des optimisations off i>?
Gardez à l'esprit qu'ils ne sont pas exactement équivalents. Vector alloue le tas par défaut, mais le tableau est sur la pile.
Bonjour Jalf, oui, cela faisait partie de ma question. J'ai également été confondu par la manière dont ils ont exécuté à la fois après l'optimisation.
Merci pour vos réponses à tous. C'est une grande communauté! Je ne peux pas croire à quelle vitesse ma question a répondu :)