• [^] # Re: Une chose que j'ai oublié d'ajouter

    Posté par . En réponse à la dépêche Le langage Rust en version 1.0 alpha, on arrête de tout casser !. Évalué à 1. Dernière modification le 02 février 2015 à 11:33.

    Enj0lras: Je ne vais pas m'attarder sur le ton condescendant de ton message. Revenons plutôt au sujet.

    Si je comprends bien ton message, tu ne comprends pas pourquoi j'utilise des entiers pour traverser un tableau alors que le C++ permet bien d'autres manières à savoir :

     for(auto it = v.begin(); it != v.end(); ++it) {
     it->doSomething();
     }

    ou encore plus simplement en C++11 :

     for (auto & element : v) {
     element.doSomething ();
     }

    La raison est la suivante. J'écris des programmes où la performance est primordiale ce qui passe entre autre par une utilisation optimale du cache des processeurs. Prenons l'exemple d'un simulateur d'écoulement de fluide où chaque cellule (imagine qu'il y a souvent 100 000 000 cellules) à des propriétés de pression, température, densité, composition, etc. On peut facilement avoir une vingtaine de paramètres. On peut utiliser une structure de donnée qui consiste à déclarer :

     struct State {
     double pressure;
     double temperature;
     ...
     double density;
     ...
     }

    et utiliser un std::vector< State > v(100 000 000). Avec une telle structure de donnée, on pourra effectivement utiliser les itérateurs. Seulement, il arrive souvent qu'on doive traverser le tableau et ne récupérer que des informations liées à la pression et la densité par exemple. Une ligne de cache fait 64 octets sur un x86-64 alors qu'un double ne fait que 8 octets. Si pressure et density ne sont pas dans la même ligne de cache, le processeur va devoir à chaque fois charger des lignes de cache pour n'utiliser qu'un huitième de l'information disponible. Le perte de performance est donc énorme.

    Une autre méthode consiste à déclarer

     struct StateVector {
     int n;
     std::vector<double> pressure;
     std::vector<double> temperature;
     ...
     std::vector<double> density;
     ...
     }

    où tous ces vecteurs ont la même longueur n, à savoir le nombre de cellules. Si maintenant, on veut faire une boucle pour n'utiliser que la pression et la density, on fait

     for (int k = 0; k < state_vector.n; ++k) {
     ...(quelque chose avec state_vector.pressure[k] et state_vector.density[k])...
     }

    L'avantage est que tout ce qui est chargé dans le cache est utilisé. Si le programme est limité par la bande passante, il peut dans ce cas être 8 fois plus rapide, ce qui est non négligeable. Maintenant, avec une telle structure de donnée, je ne vois pas comment on fait avec des itérateurs. Les index restent donc très utiles pour beaucoup de personnes.

    Si tu souhaites te renseigner, cette méthode qui consiste à utiliser des "struct of arrays" au lieu d'"arrays of structs" est une des bases de ce qu'on appelle le Data Oriented Design. Mike Acton qui s'occupe de jeux vidéos est une des personnes qui passe le plus de temps à expliquer cela. Voici une de ses conférences : https://www.youtube.com/watch?v=rX0ItVEVjHc .

    Tout cela pour dire, que non, je souffre pas d'un problème d'incompétence sur les itérateurs; j'ai seulement des besoins de performance et des solutions où les itérateurs ne peuvent pas être utilisés. Si tu as des arguments solides pour dire que l'utilisation d'entiers non signés pour indexer les tableaux est une bonne idée, prends ta plume et va écrire à Bjarne Stroustrup et Herb Sutter. Au passage, tu peux aussi écrire à Scott Meyer qui mettait déjà en garde la communauté C++ en 1995 sur les risques des entiers non signés : http://www.aristeia.com/Papers/C++ReportColumns/sep95.pdf . Il n'a malheureusement pas été entendu.