Sauf si l'on prend en compte qu'avec certains compilateurs, une affectation est de type void.Citation:
Envoyé par Médinoc
Version imprimable
Sauf si l'on prend en compte qu'avec certains compilateurs, une affectation est de type void.Citation:
Envoyé par Médinoc
Tu as une référence?Citation:
Envoyé par Miles
Est-ce que ce sont des compilateurs C? Si oui, signale leur le bug.Citation:
Envoyé par spidermario
Je n'ai pas vu de compilateur dans ce cas, j'ai simplement lu qu'il y en avait :?
Peut-être que c'est faux, j'en sais rien :roll:
Où, qu'on déconseille cette source?Citation:
Envoyé par spidermario
Bonjour,
Avant d'optimiser les performances d'execution, il faut d'abord penser a optimiser le code en lecture, i.e. ecrire du code lisible pour les humains.
On ne le repetera jamais assez, les programmes sont d'abord fait pour les humains et ensuite pour les machines.
Pense au programmeur qui reprend le code apres toi et qui passe des heures a comprendre pourquoi l'idiot precedent n'a pas voulu ecrire un code clair, tout ca pour gagner une instruction parmi des millions...
Bonjour,
les trie de la STL utilise pas mal la fonction template std::swap. Il est donc préférable que les class, possedant des variable dynamique(tableau, string, vector ...) stockées dans un contenaire implémente un swap pour optimiser les trie. Cela permet de remplacer un swap constitué de 3 operation égale( donc trois recopie de mémoire) à un échange de memoire
En posant :Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145 #include <algorithm> #include <iostream> #include <vector> #include <string> //class qui contient la fonction swap pour éviter des recopie de memoire class A { public : A(int a,std::string s) :myString(s),nb(a){ }; const std::string &GetString() {return myString;} bool operator<(const A& a)const {return nb<a.nb;} A& operator=(const A& a) { static int nbegale(0); std::cout<<"= : "<<++nbegale<<std::endl; nb=a.nb; myString=a.myString; return (*this); } void swap(A& a) { static int nbswap(0); std::cout<<"swap : "<<++nbswap<<std::endl; std::swap(nb,a.nb); myString.swap(a.myString); }; private: //varible qui "prend du temps" lors d'une recopie std::string myString; int nb; }; //specialisation de la fonction std::swap pour la class A namespace std { template<> inline void swap<A> ( A& a, A& b ) { a.swap(b); }; } int main(int argc, char** argv) { //mon vecteur a trier std::vector<A> vect; //on remplie de n'importe quoi //le but etant quil y en ai assez pour que swap soit appelé vect.push_back(A(2,"deux")); vect.push_back(A(15,"quinze")); vect.push_back(A(10,"dix")); vect.push_back(A(5,"cinq")); vect.push_back(A(1,"un")); vect.push_back(A(30,"trente")); vect.push_back(A(2,"deux")); vect.push_back(A(15,"quinze")); vect.push_back(A(10,"dix")); vect.push_back(A(5,"cinq")); vect.push_back(A(1,"un")); vect.push_back(A(30,"trente")); vect.push_back(A(2,"deux")); vect.push_back(A(15,"quinze")); vect.push_back(A(10,"dix")); vect.push_back(A(5,"cinq")); vect.push_back(A(1,"un")); vect.push_back(A(30,"trente")); vect.push_back(A(2,"deux")); vect.push_back(A(15,"quinze")); vect.push_back(A(10,"dix")); vect.push_back(A(5,"cinq")); vect.push_back(A(1,"un")); vect.push_back(A(30,"trente")); vect.push_back(A(2,"deux")); vect.push_back(A(15,"quinze")); vect.push_back(A(10,"dix")); vect.push_back(A(5,"cinq")); vect.push_back(A(1,"un")); vect.push_back(A(30,"trente")); vect.push_back(A(2,"deux")); vect.push_back(A(15,"quinze")); vect.push_back(A(10,"dix")); vect.push_back(A(5,"cinq")); vect.push_back(A(1,"un")); vect.push_back(A(30,"trente")); vect.push_back(A(2,"deux")); vect.push_back(A(15,"quinze")); vect.push_back(A(10,"dix")); vect.push_back(A(5,"cinq")); vect.push_back(A(1,"un")); vect.push_back(A(30,"trente")); vect.push_back(A(2,"deux")); vect.push_back(A(15,"quinze")); vect.push_back(A(10,"dix")); vect.push_back(A(5,"cinq")); vect.push_back(A(1,"un")); vect.push_back(A(2,"deux")); vect.push_back(A(15,"quinze")); vect.push_back(A(10,"dix")); vect.push_back(A(5,"cinq")); vect.push_back(A(1,"un")); vect.push_back(A(30,"trente")); vect.push_back(A(2,"deux")); vect.push_back(A(15,"quinze")); vect.push_back(A(10,"dix")); vect.push_back(A(5,"cinq")); vect.push_back(A(1,"un")); vect.push_back(A(30,"trente")); vect.push_back(A(2,"deux")); vect.push_back(A(15,"quinze")); vect.push_back(A(10,"dix")); vect.push_back(A(5,"cinq")); vect.push_back(A(1,"un")); vect.push_back(A(2,"deux")); vect.push_back(A(15,"quinze")); vect.push_back(A(10,"dix")); vect.push_back(A(5,"cinq")); vect.push_back(A(1,"un")); vect.push_back(A(2,"deux")); vect.push_back(A(15,"quinze")); vect.push_back(A(10,"dix")); vect.push_back(A(5,"cinq")); vect.push_back(A(1,"un")); vect.push_back(A(2,"deux")); vect.push_back(A(15,"quinze")); vect.push_back(A(10,"dix")); vect.push_back(A(5,"cinq")); vect.push_back(A(1,"un")); vect.push_back(A(2,"deux")); vect.push_back(A(15,"quinze")); vect.push_back(A(10,"dix")); vect.push_back(A(5,"cinq")); vect.push_back(A(1,"un")); vect.push_back(A(30,"trente")); vect.push_back(A(30,"trente")); vect.push_back(A(30,"trente")); vect.push_back(A(30,"trente")); vect.push_back(A(30,"trente")); vect.push_back(A(30,"trente")); //on fait le trie std::sort(vect.begin(),vect.end()); return 0; }
- duré d'un égale = 1s
- durée d'un swap = .5s (echange de la mémoire, donc peut de recopie)
Les résultats que j'obtiens sous visual 20005 sont :
- sans le swap : 234 operation egale = 234s
- avec le swap : 74 operation swap et 72 operation egale = 109 s
Les résultats que j'obtiens avec GCC sous ubuntu sont :
- sans le swap : 361 operation egale = 361s
- avec le swap : 88 operation swap et 185 operation egale = 229 s
voici un lien qui explique un peu :
http://www.tantalon.com/pete/cppopt/...l.htm#Swapping
J'ai une petite question, qu'est ce qui est le plus rapide :
code 1 :code 2:Code:
1
2 for(int i=0;i<vec.size();i++) vec[i]->unBool = false;
Je me doute bien que si "unBool" est 99% du temps à "true", le premier code sera plus rapide. Mais à partir de quel pourcentage le code numéro 2 sera plus rapide ?Code:
1
2
3 for(int i=0;i<vec.size();i++) if(vec[i]->unBool = true) vec[i]->unBool = false;
Merci d'avance
Déjà, fais attention au test que tu excécute...
En effet, si tu fais un test du genre de
tu commence par assigner true à test[i]->unBool... et donc, le test sera toujours vrai...Code:if(test[i]->unBool = true)
Pour que ce soit réellement un test, ce serait
En outre, il serait peut-être préférable de déclarer i comme étant un size_t, ce qui est le type renvoyé par size ;)Code:if(test[i]->unBool == true)
Ceci dit, il faut savoir que, si tu fais un test de manière inopportune, ce sera toujours plus lent que si tu ne le fais pas.
Il n'y a rien à faire, un test demande un certain nombre de cycle d'horloge processeur, et donc, fatalement, cela "ralenti" un peu le code :P
Pour qu'il présente un avantage, il faudrait que les instructions à effectuer dans le cas où le test est vérifié soient plus nombreuses, de manière, justement, à éviter d'effectuer le nombre d'exécutions quand elles ne sont pas nécessaire.
Ainsi, il devient opportun de placer le test si ton code doit se présenter sous une forme proche de
Code:
1
2
3
4
5
6
7
8
9
10 for(size_t i=0;i<test.size();++i) { if(test[i]->unBool == true) { /* une série d'instructions potentiellement "longue" à l'exécution * mais, en tout cas, plus importante que la simple assignation * d'un type primitif */ } }
La version avec le if sera probablement plus longue, parce que les branchements empêchent la prédiction d'instruction de fonctionner (ainsi que la vectorisation automatique).
Ma petit pierre a l'édifice :
Pour ceux qui trouvent que gcc est long a compiler (ce qui est vrai tout de même), il est important de savoir que par defaut, il le fait sur un seul thread. En utilisant l'option j, on peut augmenter le nombre de thread et profiter a fond de notre beau dual/quad core ;)
c'est pas plutot make qui a cette option ? et scons ?
GCC aussi la possède.
C'est moi qui suis distrait ou je ne la vois pas ici:
http://gcc.gnu.org/onlinedocs/gcc-4....n-Summary.html
Ou alors c'est moi qui ai fumé quelque chose de nocif pour la mémoire. Toutes mes excuses :)
de toute facon la compilation est quelque chose de sequentiel, pas vraiment beaucoup de place pour le multi core. En revanche, make a une vue d'ensemble qui permet de decouper les taches en sequences indépendantes.
La ou GCC est lent, c'est que c'est souvent utilisé en simple fichier :
alors que sous visual, en general c'est une seule instance du compilo qui fait tous les fichiers. en utilisant gcc de la meme facon, il est sensiblement plus rapide.Code:
1
2
3
4
5 gcc -c file1.cpp -o file1.obj gcc -c file2.cpp -o file2.obj gcc -c file3.cpp -o file3.obj gcc -c file4.cpp -o file4.obj gcc -c file5.cpp -o file5.obj
Depuis les derniers messages, on en sait plus sur C++0x, on a des nouvelles versions de compilos, etc.
Vous avez d'autres conseils pour ceux qui voudraient accélérer leur code ?
Par ailleurs, êtes-vous tous d'accord pour dire que C++ va rester parmi les plus rapides, devant Java et les langages .NET par exemple ? Malgré leur VM, ils obtiennent parfois de bonnes performances, mais a priori rien ne va ralentir le C++. Il est toutefois à la charge des programmeurs C++ de connaître les trucs & astuces pour avoir un code performant et bien pensé :)
C'est le vieux débat entre langages compilés et interprétés... Au fur et à mesure que la puissance de calcul augmente, les interpréteurs vont plus vite, mais les processeurs aussi quand ils exécutent un code compilé. C'est pareil pour les progrès théoriques : meilleurs interpréteurs, meilleurs compilateurs.
En ce sens, C++ conservera sa longueur d'avance. Ma seule réserve est la tendance au développement des librairies annexes. Ce n'est pas un mal en soi, mais cela transforme parfois le C++, à l'origine rapide parce que compilé et "proche de la machine" (une instruction C++=peu d'instructions machine), en un autre langage de haut niveau. Il appartient aux programmeurs C++ de savoir quand *ne pas* utiliser telle ou telle librairie ultrapuissante, dont ils n'ont pas besoin...
Mes petits conseils d'optimisation
1- ne pas trop s'inquiéter des multiplications, des floats et des doubles, des pré et post incrémentations sur types de base, le compilateur fait ça mieux que nous (et ce n'est pas du tout intuitif)...
2- se méfier comme de la peste des "bonnes idées" d'optimisation quand on fait des calculs numériques, une simplification mal à propos donne souvent des calculs très très faux. Les algorithmes mathématiques, les prendre dans des livres et des librairies spécialisées, plutôt que dans ses souvenirs de terminale (ou de prépa).
3- évaluer la volumétrie de ses programmes avant de les écrire : il ne sert à rien d'utiliser des moyens importants pour gérer efficacement une structure que comprend très peu d'objets, en revanche, savoir à l'avance qu'un petit tableau à l'air innocent contiendra probablement 1 000 000 d'objets, et pas 1000 comme on se disait au début, permet de partir sur de bonnes bases
4- quand on travaille sur de grosses données externes, se poser dès le début la question de l'ordre dans lequel on va les utiliser. Trier ses données dans le bon ordre, avant l'exécution, permet souvent de gagner sur plusieurs tableaux (mémoire et vitesse)
5- utiliser un profileur, tout le temps, presque dès le début, pas pour optimiser, mais pour savoir où le temps est passé. Généralement savoir où est le problème c'est presque le résoudre
6- résister aux sirènes des bibliothèques ultra avancées : si j'ai une date à gérer, dans un très gros tableau, il n'est pas certain que la bibliothèque dates de la mort qui tue (même du standard) me serve, peut être que juste prétendre que c'est un entier...
7- quand on optimise (à la fin) procéder en deux temps. D'abord, avec un profileur, rechercher les "erreurs bêtes", les quelques instructions ou fonctions qui perdent un temps fou et qu'on peut remplacer (généralement, des fonctions haut niveau mal à propos). Ensuite, et si nécessaire, regarder les parties du programme où le temps est passé, et y réfléchir en termes d'algorithmes ou de données...
Francois