Suite =E0 un post que j'avais ouvert r=E9cemment, j'ai isol=E9 une curiosit=
=E9
que j'aimerais =E9claircir gr=E2ce =E0 vos remarques :
J'ai une classe m=E8re A avec une methode a() virtuelle pure, et une
methode b() normale.
Je cr=E9e une classe d=E9riv=E9e B dans laquelle je mets dans a() la m=EAme
impl=E9mentation que b().
Concr=E8tement B.a(), et B.b() font la m=EAme chose.
Je caste B en A de fa=E7on =E0 utiliser plutot A.a() et A.b()
Si j'ex=E9cute ces 2 m=E9thodes un tr=E8s grand nombre de fois, je remarque
que a() est beaucoup plus lente que b().
Selon tous ces posts, mon problème est plus situé au niveau de ma configuration de compilation on dirait. Il est vrai que j'ai énormement de mal de ce côté là et qu'elle doit être assez hasard euse. J'ai créé ma release en partant de ma debug, mais j'ai du laisser passer des options importantes ... j'utilise VC2005+, connaissez-vous un bon tutoriel ? Merci d'avance
Selon tous ces posts, mon problème est plus situé au niveau de ma
configuration de compilation on dirait. Il est vrai que j'ai
énormement de mal de ce côté là et qu'elle doit être assez hasard euse.
J'ai créé ma release en partant de ma debug, mais j'ai du laisser
passer des options importantes ... j'utilise VC2005+, connaissez-vous
un bon tutoriel ? Merci d'avance
Selon tous ces posts, mon problème est plus situé au niveau de ma configuration de compilation on dirait. Il est vrai que j'ai énormement de mal de ce côté là et qu'elle doit être assez hasard euse. J'ai créé ma release en partant de ma debug, mais j'ai du laisser passer des options importantes ... j'utilise VC2005+, connaissez-vous un bon tutoriel ? Merci d'avance
Gégé
Alors j'ai un peu bidouillé les options du compilateur : j'ai changé pas mal de choses qui n'avait rien à voir avec un mode release et j'ai pu gagner encore du temps de calcul. Par contre passé un certain nombre de noeuds je constate encore que le temps s'allonge plus que linéairement. Peut-être reste-t-il des optimisations à faire dans ma config :
Voici ma config Release, qq1 aurait il des suggestions ?
Alors j'ai un peu bidouillé les options du compilateur : j'ai changé
pas mal de choses qui n'avait rien à voir avec un mode release et j'ai
pu gagner encore du temps de calcul. Par contre passé un certain
nombre de noeuds je constate encore que le temps s'allonge plus que
linéairement. Peut-être reste-t-il des optimisations à faire dans ma
config :
Voici ma config Release, qq1 aurait il des suggestions ?
Alors j'ai un peu bidouillé les options du compilateur : j'ai changé pas mal de choses qui n'avait rien à voir avec un mode release et j'ai pu gagner encore du temps de calcul. Par contre passé un certain nombre de noeuds je constate encore que le temps s'allonge plus que linéairement. Peut-être reste-t-il des optimisations à faire dans ma config :
Voici ma config Release, qq1 aurait il des suggestions ?
j'utilise VC2005+, connaissez-vous un bon tutoriel ?
Tutoriel, non, mais la site Microsoft documente toutes les options en détail. A priori, ils essaient aussi à rendre la documentation comprehensible par un débuttant, mais je suis plutôt mal placé pour juger s'ils ont réussi.
Ce que je fais, chaque fois que j'abord un nouveau compilateur, c'est de chercher une liste de toutes les options, et me démander pour chacune si je le veux ou non, en fonction de ce qu'il fait. Mais je ne suis pas sûr que ce soit une approche qui vaut pour un débuttant, parce que pour l'utiliser, il faut pouvoir comprendre la description de l'option. Si tu poses la question sur ce qu'on entend par niveau d'optimisation, c'est peu probable que tu comprendras quelque chose du genre :
-fgcse-sm When -fgcse-sm is enabled, a store motion pass is run after global common subexpression elimination. This pass will attempt to move stores out of loops. When used in conjunction with -fgcse-lm, loops containing a load/store sequence can be changed to a load before the loop and a store after the loop.
(C'est de la documentation g++, mais c'est typique du genre de jargon qu'on rencontre quand on va dans les détails.)
N'empêche que c'est sans doute comme ça que je commencerais. Quitte à essayer d'aprofondir mes connaissances quand il y a quelque chose que je ne comprends pas. À condition d'en avoir besoin---dans beaucoup de cas, le programme est assez rapide comme ça, et on peut simplement ignorer toutes les options qui concerne l'optimisation. Si ce n'est pas le cas, en revanche, il faudrait en général apprendre un peu sur l'optimisation avant de s'y attaquer. Bien que prèsque tous les compilateurs ont aussi des options « généraliste » d'optimisation, par exemple -O1, -O2 ou -O3 avec g++, et qu'un peu d'expérimentation avec celles-ci peut souvent suffire.
-- James Kanze (GABI Software) email: Conseils en informatique orientée objet/ Beratung in objektorientierter Datenverarbeitung 9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
On Nov 11, 10:22 am, Gégé <val...@gmail.com> wrote:
j'utilise VC2005+, connaissez-vous
un bon tutoriel ?
Tutoriel, non, mais la site Microsoft documente toutes les
options en détail. A priori, ils essaient aussi à rendre la
documentation comprehensible par un débuttant, mais je suis
plutôt mal placé pour juger s'ils ont réussi.
Ce que je fais, chaque fois que j'abord un nouveau compilateur,
c'est de chercher une liste de toutes les options, et me
démander pour chacune si je le veux ou non, en fonction de ce
qu'il fait. Mais je ne suis pas sûr que ce soit une approche qui
vaut pour un débuttant, parce que pour l'utiliser, il faut
pouvoir comprendre la description de l'option. Si tu poses la
question sur ce qu'on entend par niveau d'optimisation, c'est
peu probable que tu comprendras quelque chose du genre :
-fgcse-sm
When -fgcse-sm is enabled, a store motion pass is
run after global common subexpression elimination.
This pass will attempt to move stores out of loops.
When used in conjunction with -fgcse-lm, loops
containing a load/store sequence can be changed to a
load before the loop and a store after the loop.
(C'est de la documentation g++, mais c'est typique du genre de
jargon qu'on rencontre quand on va dans les détails.)
N'empêche que c'est sans doute comme ça que je commencerais.
Quitte à essayer d'aprofondir mes connaissances quand il y a
quelque chose que je ne comprends pas. À condition d'en avoir
besoin---dans beaucoup de cas, le programme est assez rapide
comme ça, et on peut simplement ignorer toutes les options qui
concerne l'optimisation. Si ce n'est pas le cas, en revanche, il
faudrait en général apprendre un peu sur l'optimisation avant de
s'y attaquer. Bien que prèsque tous les compilateurs ont aussi
des options « généraliste » d'optimisation, par exemple -O1,
-O2 ou -O3 avec g++, et qu'un peu d'expérimentation avec
celles-ci peut souvent suffire.
--
James Kanze (GABI Software) email:james.kanze@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
j'utilise VC2005+, connaissez-vous un bon tutoriel ?
Tutoriel, non, mais la site Microsoft documente toutes les options en détail. A priori, ils essaient aussi à rendre la documentation comprehensible par un débuttant, mais je suis plutôt mal placé pour juger s'ils ont réussi.
Ce que je fais, chaque fois que j'abord un nouveau compilateur, c'est de chercher une liste de toutes les options, et me démander pour chacune si je le veux ou non, en fonction de ce qu'il fait. Mais je ne suis pas sûr que ce soit une approche qui vaut pour un débuttant, parce que pour l'utiliser, il faut pouvoir comprendre la description de l'option. Si tu poses la question sur ce qu'on entend par niveau d'optimisation, c'est peu probable que tu comprendras quelque chose du genre :
-fgcse-sm When -fgcse-sm is enabled, a store motion pass is run after global common subexpression elimination. This pass will attempt to move stores out of loops. When used in conjunction with -fgcse-lm, loops containing a load/store sequence can be changed to a load before the loop and a store after the loop.
(C'est de la documentation g++, mais c'est typique du genre de jargon qu'on rencontre quand on va dans les détails.)
N'empêche que c'est sans doute comme ça que je commencerais. Quitte à essayer d'aprofondir mes connaissances quand il y a quelque chose que je ne comprends pas. À condition d'en avoir besoin---dans beaucoup de cas, le programme est assez rapide comme ça, et on peut simplement ignorer toutes les options qui concerne l'optimisation. Si ce n'est pas le cas, en revanche, il faudrait en général apprendre un peu sur l'optimisation avant de s'y attaquer. Bien que prèsque tous les compilateurs ont aussi des options « généraliste » d'optimisation, par exemple -O1, -O2 ou -O3 avec g++, et qu'un peu d'expérimentation avec celles-ci peut souvent suffire.
-- James Kanze (GABI Software) email: Conseils en informatique orientée objet/ Beratung in objektorientierter Datenverarbeitung 9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Gégé
Merci James pour ces conseils.
Toujours dans le même registre, j'aurais une question supplémentaire : y a-t-il une différence de performance entre un pointeur de fonction et une fonction virtuelle ? Ces 2 concepts me semblent assez voisins dans leur finalité. Je pourrais essayer d'alléger mon arbre en n'utilisant que des pointeurs de fonction ...
Merci James pour ces conseils.
Toujours dans le même registre, j'aurais une question supplémentaire :
y a-t-il une différence de performance entre un pointeur de fonction
et une fonction virtuelle ? Ces 2 concepts me semblent assez voisins
dans leur finalité. Je pourrais essayer d'alléger mon arbre en
n'utilisant que des pointeurs de fonction ...
Toujours dans le même registre, j'aurais une question supplémentaire : y a-t-il une différence de performance entre un pointeur de fonction et une fonction virtuelle ? Ces 2 concepts me semblent assez voisins dans leur finalité. Je pourrais essayer d'alléger mon arbre en n'utilisant que des pointeurs de fonction ...
Gégé
J'ai recréé exactement ce que je constate en mode release : a() => 3.078 sec b() => 0 sec
Si on augmente M, l'écart se creuse de plus en plus. Qu'obtenez-vous de votre côté ?
J'ai recréé exactement ce que je constate en mode release : a() => 3.078 sec b() => 0 sec
j'indiquais (il y a 2 jours) a() : 2 sec, b() 0 sec pour 1 million d'itérations; passer à 1.5 M d'itér. vérifie une certaine linéarité, cela devrait rassurer sur quel point ?
Si on augmente M, l'écart se creuse de plus en plus. Qu'obtenez-vous de votre côté ?
que cherchez-vous de votre coté ?
si vous voulez seulement (re)constater q'un appel virtuel est très lent (2 microsec), vous l'avez confirmé et si votre code fait 1 million de foi *rien*, il lui faudra du temps - mais vous pourriez choisir de faire une seule fois *rien*, le résultat sera le même et le délai plus court.
mais si votre code réalise (vraiment) quelque chose, le temps d'appel sera négligeable. certes vous pouvez remplacer votre design abstrait par de beaux pointeurs de fonctions, vous gagnerez quelque secondes, à vous de considérer s'il gagne également en lisibilité et maintenance.
Sylvain.
Gégé a écrit :
J'ai recréé exactement ce que je constate en mode release :
a() => 3.078 sec
b() => 0 sec
j'indiquais (il y a 2 jours) a() : 2 sec, b() 0 sec pour 1 million
d'itérations; passer à 1.5 M d'itér. vérifie une certaine linéarité,
cela devrait rassurer sur quel point ?
Si on augmente M, l'écart se creuse de plus en plus.
Qu'obtenez-vous de votre côté ?
que cherchez-vous de votre coté ?
si vous voulez seulement (re)constater q'un appel virtuel est très lent
(2 microsec), vous l'avez confirmé et si votre code fait 1 million de
foi *rien*, il lui faudra du temps - mais vous pourriez choisir de faire
une seule fois *rien*, le résultat sera le même et le délai plus court.
mais si votre code réalise (vraiment) quelque chose, le temps d'appel
sera négligeable. certes vous pouvez remplacer votre design abstrait
par de beaux pointeurs de fonctions, vous gagnerez quelque secondes,
à vous de considérer s'il gagne également en lisibilité et maintenance.
J'ai recréé exactement ce que je constate en mode release : a() => 3.078 sec b() => 0 sec
j'indiquais (il y a 2 jours) a() : 2 sec, b() 0 sec pour 1 million d'itérations; passer à 1.5 M d'itér. vérifie une certaine linéarité, cela devrait rassurer sur quel point ?
Si on augmente M, l'écart se creuse de plus en plus. Qu'obtenez-vous de votre côté ?
que cherchez-vous de votre coté ?
si vous voulez seulement (re)constater q'un appel virtuel est très lent (2 microsec), vous l'avez confirmé et si votre code fait 1 million de foi *rien*, il lui faudra du temps - mais vous pourriez choisir de faire une seule fois *rien*, le résultat sera le même et le délai plus court.
mais si votre code réalise (vraiment) quelque chose, le temps d'appel sera négligeable. certes vous pouvez remplacer votre design abstrait par de beaux pointeurs de fonctions, vous gagnerez quelque secondes, à vous de considérer s'il gagne également en lisibilité et maintenance.
Sylvain.
Gégé
Ce que je mets dans a() ou b() est une opération très simple ( une somme, une multiplication) et ce qui me chagrine c'est que le temps passé à effectuer cette opération élémentaire est presque négli geable devant celui passé à trouver la fonction ... c'est que je n'utilise surement pas les bons outils ... en tout cas merci pour ces bonnes paroles que je vais méditer de ce pas en me brossant les dents.
Ce que je mets dans a() ou b() est une opération très simple ( une
somme, une multiplication) et ce qui me chagrine c'est que le temps
passé à effectuer cette opération élémentaire est presque négli geable
devant celui passé à trouver la fonction ... c'est que je n'utilise
surement pas les bons outils ... en tout cas merci pour ces bonnes
paroles que je vais méditer de ce pas en me brossant les dents.
Ce que je mets dans a() ou b() est une opération très simple ( une somme, une multiplication) et ce qui me chagrine c'est que le temps passé à effectuer cette opération élémentaire est presque négli geable devant celui passé à trouver la fonction ... c'est que je n'utilise surement pas les bons outils ... en tout cas merci pour ces bonnes paroles que je vais méditer de ce pas en me brossant les dents.
Sylvain SF
Gégé a écrit :
Ce que je mets dans a() ou b() est une opération très simple ( une somme, une multiplication) et ce qui me chagrine c'est que le temps passé à effectuer cette opération élémentaire est presque négligeable devant celui passé à trouver la fonction ... c'est que je n'utilise surement pas les bons outils ... en tout cas merci pour ces bonnes paroles que je vais méditer de ce pas en me brossant les dents.
si l'opération (le traitement virtuel) est vraiment simplissime, alors en effet un modèle abstrait n'est p.e. pas la meilleure solution et un modèle plus statique basé sur un "identifieur de comportement" et un switch feront l'affaire.
eg
class A { public: enum { kAdd = 0, kMul } Operation;
A(Operation _op) { op = _op; }
/*final*/ int a(int a){ switch (op){ case kAdd: return a + 1; case kMul: return 2 * a; } return a; // unhandled }
private: Operation op; };
Sylvain.
Gégé a écrit :
Ce que je mets dans a() ou b() est une opération très simple ( une
somme, une multiplication) et ce qui me chagrine c'est que le temps
passé à effectuer cette opération élémentaire est presque négligeable
devant celui passé à trouver la fonction ... c'est que je n'utilise
surement pas les bons outils ... en tout cas merci pour ces bonnes
paroles que je vais méditer de ce pas en me brossant les dents.
si l'opération (le traitement virtuel) est vraiment simplissime, alors
en effet un modèle abstrait n'est p.e. pas la meilleure solution et un
modèle plus statique basé sur un "identifieur de comportement" et un
switch feront l'affaire.
eg
class A {
public:
enum {
kAdd = 0,
kMul
} Operation;
A(Operation _op) { op = _op; }
/*final*/ int a(int a){
switch (op){
case kAdd:
return a + 1;
case kMul:
return 2 * a;
}
return a; // unhandled
}
Ce que je mets dans a() ou b() est une opération très simple ( une somme, une multiplication) et ce qui me chagrine c'est que le temps passé à effectuer cette opération élémentaire est presque négligeable devant celui passé à trouver la fonction ... c'est que je n'utilise surement pas les bons outils ... en tout cas merci pour ces bonnes paroles que je vais méditer de ce pas en me brossant les dents.
si l'opération (le traitement virtuel) est vraiment simplissime, alors en effet un modèle abstrait n'est p.e. pas la meilleure solution et un modèle plus statique basé sur un "identifieur de comportement" et un switch feront l'affaire.
eg
class A { public: enum { kAdd = 0, kMul } Operation;
A(Operation _op) { op = _op; }
/*final*/ int a(int a){ switch (op){ case kAdd: return a + 1; case kMul: return 2 * a; } return a; // unhandled }
private: Operation op; };
Sylvain.
Fabien LE LEZ
Tu seras peut-être intéressé par cet article : http://dohp.wordpress.com/2008/10/31/implementation-of-polymorphism/
Tu seras peut-être intéressé par cet article :
http://dohp.wordpress.com/2008/10/31/implementation-of-polymorphism/
Tu seras peut-être intéressé par cet article : http://dohp.wordpress.com/2008/10/31/implementation-of-polymorphism/
Jean-Marc Bourguet
Gégé writes:
J'ai recréé exactement ce que je constate en mode release : a() => 3.078 sec b() => 0 sec
Si on augmente M, l'écart se creuse de plus en plus. Qu'obtenez-vous de votre côté ?
Dans ton exemple il est facile pour un compilateur de virer completement les appels a b() et la boucle qui ne fait donc plus rien.
Je ne suis pas sur de ce que tu mesures.
En general, il faut etre *tres* prudent sur des benchmarks synthetiques, on se retrouve tres facilement a mesurer autre chose que ce qu'on cherche a mesurer.
A+
-- Jean-Marc FAQ de fclc++: http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ C++ FAQ Lite en VF: http://www.ifrance.com/jlecomte/c++/c++-faq-lite/index.html Site de usenet-fr: http://www.usenet-fr.news.eu.org
Gégé <valasg@gmail.com> writes:
J'ai recréé exactement ce que je constate en mode release :
a() => 3.078 sec
b() => 0 sec
Si on augmente M, l'écart se creuse de plus en plus.
Qu'obtenez-vous de votre côté ?
Dans ton exemple il est facile pour un compilateur de virer completement
les appels a b() et la boucle qui ne fait donc plus rien.
Je ne suis pas sur de ce que tu mesures.
En general, il faut etre *tres* prudent sur des benchmarks synthetiques, on
se retrouve tres facilement a mesurer autre chose que ce qu'on cherche a
mesurer.
A+
--
Jean-Marc
FAQ de fclc++: http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ
C++ FAQ Lite en VF: http://www.ifrance.com/jlecomte/c++/c++-faq-lite/index.html
Site de usenet-fr: http://www.usenet-fr.news.eu.org
J'ai recréé exactement ce que je constate en mode release : a() => 3.078 sec b() => 0 sec
Si on augmente M, l'écart se creuse de plus en plus. Qu'obtenez-vous de votre côté ?
Dans ton exemple il est facile pour un compilateur de virer completement les appels a b() et la boucle qui ne fait donc plus rien.
Je ne suis pas sur de ce que tu mesures.
En general, il faut etre *tres* prudent sur des benchmarks synthetiques, on se retrouve tres facilement a mesurer autre chose que ce qu'on cherche a mesurer.
A+
-- Jean-Marc FAQ de fclc++: http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ C++ FAQ Lite en VF: http://www.ifrance.com/jlecomte/c++/c++-faq-lite/index.html Site de usenet-fr: http://www.usenet-fr.news.eu.org