Optimisation : Le for

 

Au cours d'une soirée du MVP Summit 2007, j'ai pu discuter avec Mitsu Furuta (Microsoft France) et Bruno Nati (MVP C++) et apprendre comment optimiser une boucle for (peu importe le langage utilisé).

 

Alors vous allez me dire "oui mais le for c'est nul vive les foreach". Certes c'est plus simple à utiliser mais une première optimisation c'est justement d'utiliser un for. Pourquoi ? Parce que le code ASM généré comporte une instruction en moins (une affectation).

 

Bon ça je le savais déjà, mais le plus étonnant est à venir. Voici ce qu'on a l'habitude de faire :

 

ArrayList ar = new ArrayList();
// On met X elements dans la liste (...)

// Puis on parcourt
for(int i = 0; i < ar.Length; i++)
{
Console.WriteLine(ar[i].ToString());
}

 

Et bien saviez vous que le code qui suit est plus performant ?

 

ArrayList ar = new ArrayList();
// On met X elements dans la liste (...)
// Puis on parcourt
for(int i = ar.Length - 1; i >= 0; i--)
{
Console.WriteLine(ar[i].ToString());
}

 

Pourquoi ? Je ne vais pas rentrer dans les détails parce que je ne maitrise pas vraiment, mais il se trouve que (tous) les processeurs arrêtent automatiquement les boucles une fois que l'index est arrivé à 0.

En fait il positionne automatiquement un flag une fois que cet index est arrivé à 0.

Comme cela est intégré directement dans les instructions du processeur, aucun cycle n'est nécessaire (ça ne coûte rien en temps d'exécution, ou en tout cas, infiniment moins qu'un test ou une affectation plus haut niveau).


 

Postée le 14/03/2007 par  Aleks

 

Commentaires

Posté le : 14/03/2007 Par : Patrick A

Certes, mais si tu veux avoir exactement le même comportement (affichage dans le même ordre), il faudra faire un :
Console.WriteLine(ar[ar.Length-1-i].ToString());

Et ça rajoute donc une opération supplémentaire de calcul pour chaque occurence de la boucle, ce qui risque de compenser le gain obtenu par la simplification du critère d'arret.

Il faut aussi faire attention à ne pas se tromper sur la condition d'arret, c'est ">=" qu'il faut mettre pour aller jusqu'à la fameuse valeur 0. ;-)

Posté le : 14/03/2007 Par : Aleks

Je m'attendais à ce que quelqu'un me fasse cette remarque. En fait pour respecter l'optimisation il faudra fatalement revoir sa façon de remplir ses listes à la base si l'ordre est important.

Pour le >= je corrige ...

Posté le : 04/04/2007 Par : Boon

Pour moi, c'est l'exemple typique de la fausse bonne idée.
En effet, tu gagnes une instruction dans ta boucle... mais à quel cout ?
Tu écrit un code qui est peut être moins "naturel", donc plus difficile à coder et peut être plus facilement buggé (sans parler des optimisations par le compilateur ou le moteur prédictif du processeur).
Et quel intérêt de gagner une instruction dans une boucle pour faire un tri à bulle (algo pourri de toute façon) ou afficher une liste à l'écran ?
De plus, sur toutes nos machines multi-noyaux, la réelle optimisation de performance sur les boucles importantes consisterait à passer sur plusieurs threads. Sans parler des opérations sur vecteur disponible depuis le pentium...

Posté le : 04/04/2007 Par : Aleks

Je suis tout à fait d'accord avec toi. Ce genre d'optimisation n'est a utilisé que dans des cas très précis et forcement très rares.
Je n'ais, par exemple, jamais utilisé cette astuce. Mais je trouvais ça bon de la partager avec les lecteurs de ce site.

Posté le : 23/07/2007 Par : bigpannard

C'est une bonne astuce si nous avons une imbrication de for dans un context de calcul par exemple mais le gain en temps n'est pas significatif pour rajouter une complexite a coder mais surtout une complexité lors de la lecture du code

Si vous souhaitez ajouter un commentaire vous devez être authentifié.

 

ASP MAGAZINE  ASP-PHP.NET  C²I  CodePPC  CodeS-SourceS  Dotnet-News.com  Tech Head Brothers 

Dotnet-Project.com© tous droits réservés
Webmaster Aleks. Ont collaboré à l'aboutissement de ce projet :
CodeS-SourceS.com, ASP-PHP.Net, DotNet-FR.org, C2i.fr, Newsletter ASP.NET.