Entièrement d'accord avec le point 6. Je l'aurais même mis en première position.








Entièrement d'accord avec le point 6. Je l'aurais même mis en première position.
Optimiser pour gagner 1sec je trouve que c'est du temps perdu surtout si ca doit prendre la journée
Il m'arrive souvent et c normal je pense quand j'ecris une ligne de code ou deux d'essayer de trouver la façon la plus efficace , lisible de le faire
Pourtant je suis sur que j'ai du passer outre et perdre 4-5nanosecondes
Biensur multiplié 1 seconde perdu par instruction surr 1 million l'instruction(rarement vu ça)ca fait beaucoup
Il faut vraiment se pencher sur le probleme de l'optimisation de 1 microseconde si l'application le demande(je pense au temps reel ou 1miiliseconde peut tout faire pencher)
Toutes les applications ne demande pas ce genre d'optimisation que je lis dans vos derniers posts
Développer un logiciel pour la gestion d'une pharmacie par exemple
La meuf qui est au comptoir si elle cherche le prix d'un medicament en ayant saisi le code barre( supposé une grosse bdd) Franchement le temps de reponse n'est pas une contrainte a l'application.Que cela mette 1secondes ou 3 secondes cela convient tout a fait au niveau et a l'environnent de l'utilisateur.
Enfin vous me comprenez....
PS:Je sais plus qui a dit qu'on lui avait demandé d'optimiser une boucle for pour un entretien d'embauche mais le mec devait etre sur les nerfs ce jour la
Mais c'est vrai que c'est interessant de voir cela dans la mesure ou on apprends des choses , on voit mieux ce qu'on programme enfin....
Lire tout c'est bien, mais il ne faut pas lire trop vite. L'entretiens, était, et ca a été dit par la personne concernée, pour savoir si on connaissait les optimisations faites par le compilateur. Ce test a pour but de savoir si la personne n'optimise pas pour rien. Quand vous ecrivez :
au lieu de
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3 n = (((y << 4) + (y << 3) + y) << 5) + x; n += n <<2;
Non seulement vous perdez du temps, mais, en plus, le compilateur fait quelque chose de plus rapide que vous. Le compîlateur, va faire un décalage de bits, et trois lea (pour ceux qui connaissent, lea peut être utilisé pour les multiplications par 2, 3, 4, 5, 8 et 9), ce qui est plus rapide. Et en plus vous auriez tort d'optimiser, parce que la solution la plus rapide, est effectivement de faire la multiplication par 800 explicitement en assembleur. Ce genre d'optimisation est une perte de temps inutile. (Cette expression à néanmoisn besoin d'être optimisée, mais que dans les cas, rarissimes ou vous codez une librairie graphique pour un mode graphique 800*600*24bits)
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2 n = (y * 800 + x) * 3;
Comme dit dans le post, il faut bien savoir si le code a besoin d'être optimisé ou non. Ca ne remet pas en cause ce qui a été dit dans ce post, mais, ajoutez tout de même a la liste, tout en haut en premier : "Se demander si il est interessant d'optimiser le code". C'est une optimisation très importante, celle de votre temps. Et il ne s'agit pas là seulement de reagarder si c'est optimisable ou non, mais de savoir combien on doit optimiser. La première optimisation, qui ne figure pas dans la liste, est celle de l'algorithme. Elle est très rapide en général, quand les algorithmes sont simples. C'est moins visibles souvent en POO, mais quand vous n'êtes plus dans le cadre objet, mais que vous faites abstraction du reste, par exemple lorsque vous codez une fonction a part, c'est de réflechir comme si vous êtiez un processeur, et de vous dire, par exemple "Ah, la je fais deux fois la boucle pour rien". Passé cette optimisation qui se fait très bien par tous avec un peu d'experience, les autres optimisation, ne feront jamais, gagner beacoup plus de temps, a moins de vous en faire perdre beacoup a vous, donc, il faut que ca vaille le coups. Donc pour revenir a ce que j'ai dit, il est important de se demander jusqu'a quel point il faille optimiser.
Oui il est surtout plein de vide son point 6:Envoyé par ShootDX
"Si votre code est mauvais, jetez-le."
Je vais jouer l'avocat du diable et défendre les points un par un.
1- les decalages. Je les utilise tous les jours. Pire je stocke plusieurs flags dans une variable entière et j'y accède par des masks prédéfinis sur certains bits. Pourquoi faire x << n plutot que x * 2 ^n ? Tout simplement parce que x << n est toujours plus rapide et plus simple à écrire qu'une mise à la puissance, fut-elle de deux (d'ailleurs 2^n s'écrit de manière optimale 1 << n, donc on tourne autour du pot).
La raison pour laquelle on utilise les puissances de deux dans certains algorithmes (adressage de textures, fourier transform) est justement pour pouvoir utiliser ce genre d'astuce pour faire du code plus rapide. (que ce soit sur le processeur central ou gravé dans du silicium).
Évidemment, je ne parle pas du boulet qui va aller dans tout son code à la recherche des * 2 pour les remplacer par des << 1. Ca compte pour une "désoptimisation" ça.
2 - utilisez les types dont vous avez besoin. C'est quoi cette histoire de préférer les types entiers. on ne "préfère" pas utiliser tel ou tel type, on a "besoin" d'utiliser un type float plutot qu'un type int. Je ne sais pas qui a pondu cette règle.
Par ailleurs pour parler d'éfficacité il faut juste se rappeler que utiliser des types float sur un processeur moderne est aussi rapide que d'utiliser des int (multiplication addition, je ne parle pas de la multiplication par une puissance de deux dont on a parlé plus haut). il peut être couteux par contre de faire la conversion int/float et vice versa trop souvent par ligne de code...
3- Rien à redire au 3, sauf que je pense que personne ne pensera à prendre de la mémoire dont il n'a pas besoin.
Ah si certains débutants allouent 1 Go sur la pile. Mais c'est définitivement pas bien. (attention on vous regarde !)
4- Const n'a jamais représenté un gain de place et de vitesse.
A moins qu'il n'allie ça avec la règle 2, pour dire que toutes les constantes d'un programme sont des const int ?
Au moins utiliser un #define ne posera jamais de probleme de collision de nom au linkage et utiliser un enum permettrait au moins d'avoir le nom de la constante au deboguage (et la vérification des types)..
Pour ce qui est des const *, const & et const tartempion, il faut les utiliser mais certainement pas pour ces soi-disant gains de place et de vitesse.
C'est une béquille du programmeur, pas un outil d'optimisation !
5 - Il fut un temps ou précalculer les cosinus etait bien vu par toutes les machines. A l'heure actuelles certaines machines sont tellement compliquées que vouloir y appliquer des règles simples ne t'apporteront aucun benefice.
Par exemple les processeurs modernes ont un moyen de calculer les sinus et cosinus d'un angle en une seule instruction au cout d'un nombre consequent de cycles. Et lire depuis un tableau assez important en taille mais qui n'était pas dans le cache lors de la lecture entraine un cout en cycles encore plus important. Choisissez votre camp.
Mon conseil: limitez les calculs de cosinus au strict nécessaire et ne faites le coup du tableau précalculé que si vous avez montré par A+B que cette solution vous apportera le gain nécessaire sans perdre la précision dont vous avez besoin.
Et pour savoir si vous y gagnez réllement une seule solution:
profilez, profilez et profilez encore.
LeGreg
Mon site web | Mon blog | Mes photos | Groupe USA
> BONJOUR, JE SUIS NOUVEAU SUR CE FORUM
> presse la touche caps lock, stp
> OH.. MERCI C EST BEAUCOUP PLUS FACILE COMME CA
C'est à moi qu'on a demandé ça.Envoyé par hegros
Je ne sais pas si le recruteur était sur les nerfs, c'était chez Electronic Arts et j'ai eu une offre (que j'ai déclinée).
Le but ce n'est pas d'optimiser une boucle. La plupart des questions posées en entretien n'ont aucune application concrete. Au moins pour les questions demandées aux débutants ce sont souvent des problèmes déjà résolus mais qui permettent juste de jauger de la réactivité d'un candidat.
Mais bon si je l'ai citée plus haut c'est juste parce que je trouvais l'idée interessante.
En general il y a peu de questions d'optimisations dans les entretiens que j'ai passé, surtout de la correction de code, beaucoup de calculs mathématiques formels ou l'écriture d'algos non triviaux en temps limité.
L'optimisation c'est la cerise sur le gateau et ce sont souvent des trucs de collègiens, probablement pour jauger ta "culture de programmation".
LeGreg
Mon site web | Mon blog | Mes photos | Groupe USA
> BONJOUR, JE SUIS NOUVEAU SUR CE FORUM
> presse la touche caps lock, stp
> OH.. MERCI C EST BEAUCOUP PLUS FACILE COMME CA
Le Memcpy générique n'est pas particulièrement optimisé, meme si c'est vrai que le code est simple.Envoyé par Metal Tom
Avec une réécriture qui utilise le support MMX (présent depuis de nombreuses années dans les processeurs), le memcopy de base va deux fois plus vite.
Ce n'est certes pas un gain tel qu'on change d'ordre de grandeur comme faire le memcopy en temps logarithmique du nombre de cases mémoires (mais qui sait un jour peut-etre). Mais deux fois plus vite si c'est pour copier de grandes zones de données ou des images, ce n'est pas à cracher dessus.
LeGreg
Mon site web | Mon blog | Mes photos | Groupe USA
> BONJOUR, JE SUIS NOUVEAU SUR CE FORUM
> presse la touche caps lock, stp
> OH.. MERCI C EST BEAUCOUP PLUS FACILE COMME CA








Pour parcourir tous les éléments d'une chaîne terminée par un '\0' ('\0'-terminated string), au lieu de faire:
on peut faire:
Code : Sélectionner tout - Visualiser dans une fenêtre à part for (int i = 0; i < strlen(str); i++) {}
Effectivement, strlen() doit forcément parcourir toute la chaîne pour trouver un '\0', incrémenter un compteur, etc.
Code : Sélectionner tout - Visualiser dans une fenêtre à part for (const char* cur = str; *cur != '\0'; cur++) {}
je veux savoir comment le parcours d'un tableau a l'aide de pointeur est plus rapide qu'un int i;
merci








Ca revient au même (optimisation de la part du compilateur).je veux savoir comment le parcours d'un tableau a l'aide de pointeur est plus rapide qu'un int i;
merci
Honnêtement, je ne vois pas trop dans quel cas pratique on a besoin de parcourir un tableau de char. Si on se met à écrire du code comme celui-là, il faut se demander si on n'a pas intérêt à utiliser la classe std::string. Dans 99% des cas, la réponse est oui.Envoyé par ShootDX
* Pour continuer sur les chaînes de caractères, éviter au maximum les printf, sprintf et dérivés, qui sont des usines à gaz. Leur préférer si possible puts (bcp plus simples car pas de formatage) et les opérateurs de C++ cin/cout<< (qui font un maximum de boulot du formatage à la compilation).
* Retarder/limiter le plus possible les opérations de fichier, forcément lentes, en créant des buffers si nécessaire.
* Utiliser la STL = plus de généricité et moins de bugs dans les algos.
Et dans ce cas, utiliser les bons conteneurs et les bons algorithmes aux bons moment.
std::vector (ou pire un tableau C) n'est pas le conteneur le plus adapté pour faire un dictionnaire (accès en O(n)). Un std::map (en O(log n)) ou mieux, un std::hash_map sera nettement plus indiqué (O(1)). De même, pour les grosses allocations, std::deque peut s'avérer plus intéressant que std::vector (ou pire un tableau C).
A part pour des domaines très spécifiques, dès qu'on a affaire à un traitement un peu compliqué (recherche dans un tableau, merge, recherche d'inclusions, etc), vérifier si l'algo n'existe pas déjà dans la STL ou dans des librairies existantes.
* Eviter de créer des hiérarchies de classes de hauteur trop profonde. Au-dela de 4 niveaux, il faut commencer à se poser des questions et chercher à "étaler" une hiérarchie horizontalement. L'accumulation des constructeurs et des destructeurs finit par tuer les performances (voir les librairies java), sans parler de la gestion des exceptions qui peut devenir rapidement problématique. En général, faire des hiérarchies compliquées n'est pas bon signe en OO, -en C++ en tout cas-.
L'utilisation de classes paramétrées (class templates), peut parfois aider. Mais attention à ne pas en abuser, car les templates ne remplacent pas les classes : pas de hiérarchie possible, et le code devient vite illisible, donc une bonne règle à respecter est qu'il faut ne les utiliser qu'avec les types de base en paramètre (int, char, float, boo et int*, char*, float*, bool*l).
Et profiler, profiler, bien évidemment.
ps : l'optimisation du code ne doit pas être une excuse pour ne pas utiliser les techniques connues pour améliorer la robustesse du code, comme les auto_ptr, l'usage de const, des classes stack-based, etc.
En terme de rapidité de code, le premier aspect à aborder est l'efficacité de l'algorithme utilisé ainsi que les collections utilisées selon le nombre de données et l'accès qu'on y fera (liste simple, chainées, hash table, etc.)
Après ça, les autres améliorations perfos restent minimes par rapport au temps consacré.

théoriquement on peux utiliser l'un ou l'autre.... mais il arrive que l'on soit obligé de préférer l'un à l'autre...2 - utilisez les types dont vous avez besoin. C'est quoi cette histoire de préférer les types entiers. on ne "préfère" pas utiliser tel ou tel type, on a "besoin" d'utiliser un type float plutot qu'un type int. Je ne sais pas qui a pondu cette règle.
d'ailleurs je ne sais pas s'il est plus rapide de convertir les float en int afin de travailler plus rapidement avec les int, ou de rester en float ?








Si tes floats sont entières (exposant >= 0), alors je dirais que ça dépend du nombre d'opérations et de leur type:
Code : Sélectionner tout - Visualiser dans une fenêtre à part d'ailleurs je ne sais pas s'il est plus rapide de convertir les float en int afin de travailler plus rapidement avec les int, ou de rester en float ?
1. Pour additionner deux flottants ou trouver leur différence, il faut aligner leurs exposants (pas besoins pour les multiplications/divisions).
2. Pour convertir un flottant en entier, on ne prend que les (m-e) premiers bits du mantisse en considération, où m est le nombre de bits de celui-ci et e l'exposant du flottant.
Si tes floats ne sont pas entières, il faut voir du côté des décimaux à virgule fixe (exemple: tous les nombres à manipuler sont déjà alignés sur le même exposant, on ne fait que des opérations sur le mantisse).
Bonjour, j'avoue ne pas avoir lu les 8 pages de réponses alors j'espère que je ne vais pas répéter quelqu'un.
Pour vioir les fonctions qui prennent le plus de temps d'exécution, il faut utiliser le profiler (lors de la compilation, il faut compiler avec l'option -pg
Ce profiler renvoie le temps d'exécution de chacune des fonctions utilisées. Ainsi, on sait tout de suite qu'elle partie du prgm retravailler.
Des exemples:Envoyé par el muchacho
Implémenter un parser de langage ou un générateur de code.
Reconnaitre dans un flux de caractères les mots réservés d'un langage. Faire de la surbrillance de sa syntaxe.
Développer un outil qui met en place des balises Doxygen sur des sources existant non documentés.
Ecrire un programme qui parse un source afin de remonter des graphes de contrôle ...
Et pour tous ces cas, il vaut mieux du code C optimisé à l'utilisation de la STL.
Je ne vois pas où sont ces usines à gaz? Certes, les flux C++ sont plus jolis, mais je regrette franchement le formatage de chaîne parfois.Envoyé par el muchacho
Oui, et puts ne dois pas être utilisée en même temps que les flux, sinon plantage, au passage. Ainsi que fgets, printf ... Enfin, ça dépend des compilateurs.Envoyé par el muchacho
Excellent conseil, sauf pour les fichiers de logs servant à debuguer.Envoyé par el muchacho
Je suis d'accord, dans les applications de haut niveau, la STL est bien. Par contre, tous les domaines de développement ne demandent pas les même temps de réponses, par exemple le temps réel embarqué.Envoyé par el muchacho
De plus, il y a souvent un surcoût non négligeable en mémoire.
On gagne en sécurité et en économie de code ce que l'on perd en performances et économie mémoire.
Excellent, tout le monde devrait suivre ce conseil.Envoyé par el muchacho
Il n'est pas toujours possible de profiler, notamment quand le code est embarqué, que le seul profiler possible est un profiler ICE qui coûte plusieur milliers d'euro.Envoyé par el muchacho
Non, il est plus rentable parfois de générer le code en assembleur, et de calculer les temps d'exécution à partir de l'assembleur. ( Très long et très fastidfieux.)
L'explication est donnée un peu plus haut dans le topic.Envoyé par amiro
Pour la liste de LeGreg, le point 3. Les const, j'en use énormément dans le code que je dois implémenter pour du calcul matriciel. J'ai une classe de matrice, mais quand une opération d'addition crée une nouvelle matrice, il renvoie celle-ci, donc impossible d'utiliser le passage par référence dans mon code si je veux pouvoir faire des calculs comme avec des entiers. Cela fait que les const sont super pratiques car passés avec un argument ou comme effet de la méthode, ça indique au compilateur qu'il n'aura pas besoin de créer un nouvel objet. Ensuite, à lui de voir s'il va effectivement se passer du constructeur ou pas.








++ i est plus rapide que i++
idem pour -- i a la place de i--
Cordialement








parcours d'une chaine
char * chaine = "salut les copines";
char * pt = chaine;
while (* pt)
{
//ce que je dois faire .....
pt ++
}








utiliser l'operateur * plutot que l'opérateur /
float toto = 2;
float titi = toto / 2 ;//pas terrible ...
float titi = toto * 0.5; //meilleur, plus rapide enfin c'est
//ce que je faisais avec de vieux compilo et je continue
//par habitude, mais je n'ai aucune certitude, a voir ...
Je pense que les compilateurs actuels optimisent tout seul ce genre de calcul.Envoyé par lepoutho
Ils peuvent même utiliser les registres spécialisés en nombre à virgule. Mais c'est vrai que je n'ai pas personnellement vérifié, j'ai juste lu la documentation.
Open Source Microsoft MediaFoundation
https://github.com/mofo7777
http://jeux.developpez.com/faq/directx/?page=dshow
Partager