2010-12-06 5 views
1

Quel est le meilleur (en performance) parmi ces extraits?Performance compare (appel de fonction normale vs for_each + mem_fun vs expression lambda) en C++

1)

for(list<Enemy*>::iterator iter = enemies.begin(); iter != enemies.end(); iter ++) 
    (*iter)->prepare(time_elapsed); 

2)

for_each(enemies.begin(), enemies.end(), [time_elapsed] (Enemy *e) {e->prepare(time_elapsed);}); 

3)

for_each(enemies.begin(), enemies.end(), bind2nd(mem_fun1<void, Enemy, GLfloat>(&Enemy::prepare), time_elapsed)); 
+8

Vous pouvez facilement mesurer vous-même dans le temps qu'il faut à quelqu'un pour mettre en place une réponse. – spender

+0

Je pense que 2 a la meilleure chance. (1) a quelques inefficacités (appelant 'end' plusieurs fois et en utilisant post-incrément). – lijie

+0

Enveloppez chaque instruction dans une étendue et placez un 'boost :: progress_timer' au début de la portée. Cela vous le dira. –

Répondre

1

Les Lambda sont la solution la plus rapide. Des optimisations spéciales sont nécessaires pour prendre des références à des variables basées sur une pile. En outre, en C++ 0x, ils sont plus flexibles que n'importe lequel de ces éléments de liaison, et la première boucle a également l'inconvénient de la clarté. Les Lambdas sont le winrar dans tous les sens.

Cependant, je pense sérieusement à la micro-optimisation, à moins que ce ne soit dans une boucle vraiment, vraiment interne qui court des milliards de fois.

0

2 et 3 sont essentiellement identiques. 1 peut être plus rapide car il effectue un appel de fonction par itération alors que 2 et 3 effectuent deux appels de fonction par itération. Là encore, certains des appels de fonction peuvent être insérés. La seule façon de vraiment dire est de mesurer.

De plus, puisque vous lancer dans des fonctions lambda (C++ 0x), pourquoi ne pas ajouter à base gamme pour les boucles à vos mesures:

for (var iter : enemies) { iter->prepare(time_lapsed); } 

en supposant que votre compilateur les prend en charge, bien sûr.

EDIT: Je viens de remarquer la balise vC++ 2010. Malheureusement, votre compilateur ne les supporte pas encore :-(

+0

2 et 3 ne sont pas identiques. Le composant bind/mem_fun est beaucoup plus difficile à intégrer pour le compilateur, car vous liez la fonction lors de l'exécution. – jalf

+0

l'inline dépend aussi de la mise en œuvre de la méthode "prepare" à droite? – bubman

0

J'ai fait les measurations sans optimisations du compilateur:

2) et 3) ont presque le même temps de fonctionnement, au lieu 1) est 10 fois plus lent. J'ai ajouté aussi 4)

for each (Enemy* e in enemies) 
     e->prepare(time_elapsed); 

valide pour Visual C++ 2010 et devrait être sematically même de son Ferruccio:

for (var iter : enemies) { iter->prepare(time_elapsed); } 

4) est également presque aussi vite que 2) et 3).

Avec -O2 tous ont presque le même temps de fonctionnement.

+2

À quoi bon faire des mesures de performance sans optimisations? Si vous êtes intéressé par la performance, pourquoi auriez-vous des optimisations? – AshleysBrain

0

La réponse est « ce n'est pas du tout important jusqu'à ce que vous avez mesuré que quelque chose est actuellement pas assez vite ». Cette question est essentiellement une optimisation prématurée. Jusqu'à ce que soit trop lent et vous avez mesuré la boucle comme étant un goulot d'étranglement, votre priorité est de utilisez le code qui communique ce que vous essayez de faire de la manière la plus claire. Écrivez d'abord du code sympa, optimisez plus tard.

+0

Dans mon code, je n'ai pas vraiment besoin d'optimisation, c'est juste une curiosité pour l'avenir – bubman