Est-on assur=E9 que les =E9l=E9ments d'un std::vector se suivent en m=E9moi=
re?
Je veux utiliser un vector pour me d=E9charger de l'allocation dynamique
t'un tableau temporaire de caract=E8res.
Ca marche sous VC++ 2003.
Mais est-ce standard et/ou portable?
J'ai aussi essay=E9 ceci, mais =E7a ne marche pas dans tous les cas et
=E9clanche parfois des exceptions. Je soupsonne l'impl=E9mentation de ne
pas vraiment effectuer le reserve().
Rq: je ne peux pas me permettre d'utiliser les iostreams pour des
raisons de performance. La fonction parser doit interpr=E9ter des
fichiers de plusieurs centaines de ko de texte.
Si un compilateur soit disant évolué appelle sqrt à chaque itération, il est pas très malin puisque pi et sqrt sont connues au moment de la compilation*.
Il le fait, en revanche. Parce que comment sait-il que sqrt(7) renvoie toujours la même valeur ?
Parce qu'il a une boule de cristal!
sqrt fait partie de la bibliotheque standard: avec les bonnes incantations, genre #include <cmath>, le compilateur est en droit de faire toute la magie qu'il veut, meme si ce ne sont pas des choses exprimables en C++ portable.
En particulier, le compilateur peut tres bien savoir qu'il s'agit d'une `vraie' fonction, et optimiser en consequence.
In article <1174380448.565549.65170@b75g2000hsg.googlegroups.com>,
James Kanze <james.kanze@gmail.com> wrote:
Si un compilateur soit disant évolué appelle sqrt à chaque itération,
il est pas très malin puisque pi et sqrt sont connues au moment de la
compilation*.
Il le fait, en revanche. Parce que comment sait-il que sqrt(7)
renvoie toujours la même valeur ?
Parce qu'il a une boule de cristal!
sqrt fait partie de la bibliotheque standard: avec les bonnes
incantations, genre #include <cmath>, le compilateur est en droit
de faire toute la magie qu'il veut, meme si ce ne sont pas des
choses exprimables en C++ portable.
En particulier, le compilateur peut tres bien savoir qu'il s'agit
d'une `vraie' fonction, et optimiser en consequence.
Si un compilateur soit disant évolué appelle sqrt à chaque itération, il est pas très malin puisque pi et sqrt sont connues au moment de la compilation*.
Il le fait, en revanche. Parce que comment sait-il que sqrt(7) renvoie toujours la même valeur ?
Parce qu'il a une boule de cristal!
sqrt fait partie de la bibliotheque standard: avec les bonnes incantations, genre #include <cmath>, le compilateur est en droit de faire toute la magie qu'il veut, meme si ce ne sont pas des choses exprimables en C++ portable.
En particulier, le compilateur peut tres bien savoir qu'il s'agit d'une `vraie' fonction, et optimiser en consequence.
Franck Branjonneau
Sylvain Togni <"sylvain.togni at visionobjects.com"> écrivait:
Je ne sais pas, la seule différence que je vois c'est qu'en utilisant const on est assez souvent amené à définir deux fois certaines fonctions comme les getteurs, une version const et une version non-const, ce qui augmente la taille du code et diminue un peu la vitesse pour des raisons de localité.
Moi, un getteur non const j'appelle ça un setteur.
-- Franck Branjonneau
Sylvain Togni <"sylvain.togni at visionobjects.com"> écrivait:
Je ne sais pas, la seule différence que je vois c'est qu'en
utilisant const on est assez souvent amené à définir deux fois
certaines fonctions comme les getteurs, une version const et
une version non-const, ce qui augmente la taille du code et
diminue un peu la vitesse pour des raisons de localité.
Moi, un getteur non const j'appelle ça un setteur.
Sylvain Togni <"sylvain.togni at visionobjects.com"> écrivait:
Je ne sais pas, la seule différence que je vois c'est qu'en utilisant const on est assez souvent amené à définir deux fois certaines fonctions comme les getteurs, une version const et une version non-const, ce qui augmente la taille du code et diminue un peu la vitesse pour des raisons de localité.
Moi, un getteur non const j'appelle ça un setteur.
-- Franck Branjonneau
James Kanze
On Mar 20, 11:20 am, Sylvain Togni <"sylvain.togni at visionobjects.com"> wrote:
James Kanze wrote:
Un petit essai (pas très rigueureux) montre que le const fait une différence et avec g++ et avec Sun CC sous Solaris, et avec g++ sous Linux. Essaie donc :
double const d = 1.0009 ; double tot1 = 1.0 ; double tot2 = 1.0 ; for ( int i = 0 ; i < 1000000000 ; ++ i ) { f( d ) ; tot1 += 2.0 * d + 1.0 ; tot2 += 3.0 * d + 2.0 ; }
Avec « void f( double const& ) ». Puis sans le const sur d. Les temps sont bien différents.
C'est vrai que dans ce genre de situations le const peut faire une différence. Mais sont-elles vraiment courantes ? Tu passes souvent des doubles par référence constante ?
Quand j'instancie un template ?
En fait, je crois qu'il s'agit plutôt d'une convention. Remplace le double par std::complex< double >, par exemple, et il y a de fortes chances que tu le passes de temps en temps par référence (or que toutes les fonctions en sont inline, et un bon compilateur génèrera souvent du code comme si tu avais deux doubles).
Aussi, bizarrement, j'ai essayé ce code avec 3 compilateurs différents et jamais la version const n'a gagné.
C'est très bizarre, parce qu'un de mes tests, c'était bien g++ (4.1.0) sous Linux. Sur un PC donc, et où je m'attendrais à exactement les mêmes résultats que sous Windows. Est-ce que tu es sûr 1) d'avoir compilé avec -O3, et 2) d'avoir mis f dans une unité de traduction compilée à part. (g++ inline s'il voit la définition, même si toi tu ne l'as pas démandé.)
- VC6 ne fait aucune optimisation, en const comme en non-const et génère strictement le même code assembleur.
- VC8 fait une optimisation globale (j'ai pourtant mi la définition de f dans une unité à part), supprime l'appel à f et pré-calcul les deux incréments, en const comme en non-const.
- GCC pré-calcul les deux incréments seulement en const, effectivement, mais bizarrement cela se traduit par une vitesse moindre de la version avec const (Vive les architectures modernes ;-).
C'est bizarre quand même. A priori, vue les temps (surtout la différence entre VC8 et les autres), ce que tu mesures réelement, c'est le temps d'appel d'une fonction (et les différences ne reflète que la manque de précision dans les mesures). J'ai eu un effet semblable dans mon premier essai, où je n'avais qu'une seule expression « tot += 2.1 * d ». Mais je le trouve quand même étonnant que j'arrive à voir une différence nette (15-20%, systèmatique) sur PC sous Linux. Est-ce qu'il y a une différence aussi importante dans la séquence d'un appel de fonction, due à une API différente ? (Si quelqu'un a accès à une machine dual-boot, ça serait intéressant de voir les mesures avec la même version de g++, une fois sous Windows, une fois sous Linux.)
De toute façon, je crois qu'on peut bien dire que dans la plupart des programmes, la différence ne sera pas importante, et qu'on ne doit pas faire la décision d'office sur la base des performances. Si par la suite, il y a un problème de performance, et qu'on ne met pas le const d'office, on peut toujours l'ajouter, histoire de voir. Si ça rapporte, on le laisse (avec un commentaire). Sinon, le coût de l'essai a quand même était minimal. (Moins même que d'essayer avec f() inline.)
-- 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 Mar 20, 11:20 am, Sylvain Togni <"sylvain.togni at
visionobjects.com"> wrote:
James Kanze wrote:
Un petit essai (pas très rigueureux) montre que le const fait
une différence et avec g++ et avec Sun CC sous Solaris, et avec
g++ sous Linux. Essaie donc :
double const d = 1.0009 ;
double tot1 = 1.0 ;
double tot2 = 1.0 ;
for ( int i = 0 ; i < 1000000000 ; ++ i ) {
f( d ) ;
tot1 += 2.0 * d + 1.0 ;
tot2 += 3.0 * d + 2.0 ;
}
Avec « void f( double const& ) ». Puis sans le const sur d.
Les temps sont bien différents.
C'est vrai que dans ce genre de situations le const peut
faire une différence. Mais sont-elles vraiment courantes ?
Tu passes souvent des doubles par référence constante ?
Quand j'instancie un template ?
En fait, je crois qu'il s'agit plutôt d'une convention. Remplace
le double par std::complex< double >, par exemple, et il y a de
fortes chances que tu le passes de temps en temps par référence
(or que toutes les fonctions en sont inline, et un bon
compilateur génèrera souvent du code comme si tu avais deux
doubles).
Aussi, bizarrement, j'ai essayé ce code avec 3 compilateurs
différents et jamais la version const n'a gagné.
C'est très bizarre, parce qu'un de mes tests, c'était bien g++
(4.1.0) sous Linux. Sur un PC donc, et où je m'attendrais à
exactement les mêmes résultats que sous Windows. Est-ce que tu
es sûr 1) d'avoir compilé avec -O3, et 2) d'avoir mis f dans une
unité de traduction compilée à part. (g++ inline s'il voit la
définition, même si toi tu ne l'as pas démandé.)
- VC6 ne fait aucune optimisation, en const comme en
non-const et génère strictement le même code assembleur.
- VC8 fait une optimisation globale (j'ai pourtant mi la
définition de f dans une unité à part), supprime l'appel
à f et pré-calcul les deux incréments, en const comme
en non-const.
- GCC pré-calcul les deux incréments seulement en const,
effectivement, mais bizarrement cela se traduit par une
vitesse moindre de la version avec const (Vive les
architectures modernes ;-).
C'est bizarre quand même. A priori, vue les temps (surtout la
différence entre VC8 et les autres), ce que tu mesures
réelement, c'est le temps d'appel d'une fonction (et les
différences ne reflète que la manque de précision dans les
mesures). J'ai eu un effet semblable dans mon premier essai, où
je n'avais qu'une seule expression « tot += 2.1 * d ». Mais je
le trouve quand même étonnant que j'arrive à voir une différence
nette (15-20%, systèmatique) sur PC sous Linux. Est-ce qu'il y a
une différence aussi importante dans la séquence d'un appel de
fonction, due à une API différente ? (Si quelqu'un a accès à
une machine dual-boot, ça serait intéressant de voir les mesures
avec la même version de g++, une fois sous Windows, une fois
sous Linux.)
De toute façon, je crois qu'on peut bien dire que dans la
plupart des programmes, la différence ne sera pas importante, et
qu'on ne doit pas faire la décision d'office sur la base des
performances. Si par la suite, il y a un problème de
performance, et qu'on ne met pas le const d'office, on peut
toujours l'ajouter, histoire de voir. Si ça rapporte, on le
laisse (avec un commentaire). Sinon, le coût de l'essai a quand
même était minimal. (Moins même que d'essayer avec f() inline.)
--
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
On Mar 20, 11:20 am, Sylvain Togni <"sylvain.togni at visionobjects.com"> wrote:
James Kanze wrote:
Un petit essai (pas très rigueureux) montre que le const fait une différence et avec g++ et avec Sun CC sous Solaris, et avec g++ sous Linux. Essaie donc :
double const d = 1.0009 ; double tot1 = 1.0 ; double tot2 = 1.0 ; for ( int i = 0 ; i < 1000000000 ; ++ i ) { f( d ) ; tot1 += 2.0 * d + 1.0 ; tot2 += 3.0 * d + 2.0 ; }
Avec « void f( double const& ) ». Puis sans le const sur d. Les temps sont bien différents.
C'est vrai que dans ce genre de situations le const peut faire une différence. Mais sont-elles vraiment courantes ? Tu passes souvent des doubles par référence constante ?
Quand j'instancie un template ?
En fait, je crois qu'il s'agit plutôt d'une convention. Remplace le double par std::complex< double >, par exemple, et il y a de fortes chances que tu le passes de temps en temps par référence (or que toutes les fonctions en sont inline, et un bon compilateur génèrera souvent du code comme si tu avais deux doubles).
Aussi, bizarrement, j'ai essayé ce code avec 3 compilateurs différents et jamais la version const n'a gagné.
C'est très bizarre, parce qu'un de mes tests, c'était bien g++ (4.1.0) sous Linux. Sur un PC donc, et où je m'attendrais à exactement les mêmes résultats que sous Windows. Est-ce que tu es sûr 1) d'avoir compilé avec -O3, et 2) d'avoir mis f dans une unité de traduction compilée à part. (g++ inline s'il voit la définition, même si toi tu ne l'as pas démandé.)
- VC6 ne fait aucune optimisation, en const comme en non-const et génère strictement le même code assembleur.
- VC8 fait une optimisation globale (j'ai pourtant mi la définition de f dans une unité à part), supprime l'appel à f et pré-calcul les deux incréments, en const comme en non-const.
- GCC pré-calcul les deux incréments seulement en const, effectivement, mais bizarrement cela se traduit par une vitesse moindre de la version avec const (Vive les architectures modernes ;-).
C'est bizarre quand même. A priori, vue les temps (surtout la différence entre VC8 et les autres), ce que tu mesures réelement, c'est le temps d'appel d'une fonction (et les différences ne reflète que la manque de précision dans les mesures). J'ai eu un effet semblable dans mon premier essai, où je n'avais qu'une seule expression « tot += 2.1 * d ». Mais je le trouve quand même étonnant que j'arrive à voir une différence nette (15-20%, systèmatique) sur PC sous Linux. Est-ce qu'il y a une différence aussi importante dans la séquence d'un appel de fonction, due à une API différente ? (Si quelqu'un a accès à une machine dual-boot, ça serait intéressant de voir les mesures avec la même version de g++, une fois sous Windows, une fois sous Linux.)
De toute façon, je crois qu'on peut bien dire que dans la plupart des programmes, la différence ne sera pas importante, et qu'on ne doit pas faire la décision d'office sur la base des performances. Si par la suite, il y a un problème de performance, et qu'on ne met pas le const d'office, on peut toujours l'ajouter, histoire de voir. Si ça rapporte, on le laisse (avec un commentaire). Sinon, le coût de l'essai a quand même était minimal. (Moins même que d'essayer avec f() inline.)
-- 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
Sylvain Togni
James Kanze wrote:
Un petit essai (pas très rigueureux) montre que le const fait une différence et avec g++ et avec Sun CC sous Solaris, et avec g++ sous Linux. Essaie donc :
double const d = 1.0009 ; double tot1 = 1.0 ; double tot2 = 1.0 ; for ( int i = 0 ; i < 1000000000 ; ++ i ) { f( d ) ; tot1 += 2.0 * d + 1.0 ; tot2 += 3.0 * d + 2.0 ; }
Avec « void f( double const& ) ». Puis sans le const sur d. Les temps sont bien différents.
Aussi, bizarrement, j'ai essayé ce code avec 3 compilateurs différents et jamais la version const n'a gagné.
C'est très bizarre, parce qu'un de mes tests, c'était bien g++ (4.1.0) sous Linux. Sur un PC donc, et où je m'attendrais à exactement les mêmes résultats que sous Windows. Est-ce que tu es sûr 1) d'avoir compilé avec -O3, et 2) d'avoir mis f dans une unité de traduction compilée à part. (g++ inline s'il voit la définition, même si toi tu ne l'as pas démandé.)
Oui, j'ai mis la fonction f (vide) dans une unité compilée à part, et j'ai utilisé les options d'optimisation maximales des 3 compilateurs.
L'appel à f prend 80% du temps environ, c'est pour cela que VC8, qui l'a supprimée grâce à son analyse globale, est bien meilleur.
Quant à GCC, je pense que c'est par un malheureux hasard que sur ma machine la version non-const est plus rapide. Un coup d'oeil au code assembleur montre que la boucle avec le const contient 2 fois moins d'instructions, mais sur les architectures modernes moins d'instructions ne veut pas forcément dire plus rapide.
De toute façon, je crois qu'on peut bien dire que dans la plupart des programmes, la différence ne sera pas importante, et qu'on ne doit pas faire la décision d'office sur la base des performances. Si par la suite, il y a un problème de performance, et qu'on ne met pas le const d'office, on peut toujours l'ajouter, histoire de voir. Si ça rapporte, on le laisse (avec un commentaire). Sinon, le coût de l'essai a quand même était minimal. (Moins même que d'essayer avec f() inline.)
Oui, et on peut aussi dire qu'un bon compilateur/optimisateur vaut mieux que mille consts.
-- Sylvain Togni
James Kanze wrote:
Un petit essai (pas très rigueureux) montre que le const fait
une différence et avec g++ et avec Sun CC sous Solaris, et avec
g++ sous Linux. Essaie donc :
double const d = 1.0009 ;
double tot1 = 1.0 ;
double tot2 = 1.0 ;
for ( int i = 0 ; i < 1000000000 ; ++ i ) {
f( d ) ;
tot1 += 2.0 * d + 1.0 ;
tot2 += 3.0 * d + 2.0 ;
}
Avec « void f( double const& ) ». Puis sans le const sur d.
Les temps sont bien différents.
Aussi, bizarrement, j'ai essayé ce code avec 3 compilateurs
différents et jamais la version const n'a gagné.
C'est très bizarre, parce qu'un de mes tests, c'était bien g++
(4.1.0) sous Linux. Sur un PC donc, et où je m'attendrais à
exactement les mêmes résultats que sous Windows. Est-ce que tu
es sûr 1) d'avoir compilé avec -O3, et 2) d'avoir mis f dans une
unité de traduction compilée à part. (g++ inline s'il voit la
définition, même si toi tu ne l'as pas démandé.)
Oui, j'ai mis la fonction f (vide) dans une unité compilée
à part, et j'ai utilisé les options d'optimisation maximales
des 3 compilateurs.
L'appel à f prend 80% du temps environ, c'est pour cela que
VC8, qui l'a supprimée grâce à son analyse globale, est bien
meilleur.
Quant à GCC, je pense que c'est par un malheureux hasard que
sur ma machine la version non-const est plus rapide. Un coup
d'oeil au code assembleur montre que la boucle avec le const
contient 2 fois moins d'instructions, mais sur les
architectures modernes moins d'instructions ne veut pas
forcément dire plus rapide.
De toute façon, je crois qu'on peut bien dire que dans la
plupart des programmes, la différence ne sera pas importante, et
qu'on ne doit pas faire la décision d'office sur la base des
performances. Si par la suite, il y a un problème de
performance, et qu'on ne met pas le const d'office, on peut
toujours l'ajouter, histoire de voir. Si ça rapporte, on le
laisse (avec un commentaire). Sinon, le coût de l'essai a quand
même était minimal. (Moins même que d'essayer avec f() inline.)
Oui, et on peut aussi dire qu'un bon compilateur/optimisateur
vaut mieux que mille consts.
Un petit essai (pas très rigueureux) montre que le const fait une différence et avec g++ et avec Sun CC sous Solaris, et avec g++ sous Linux. Essaie donc :
double const d = 1.0009 ; double tot1 = 1.0 ; double tot2 = 1.0 ; for ( int i = 0 ; i < 1000000000 ; ++ i ) { f( d ) ; tot1 += 2.0 * d + 1.0 ; tot2 += 3.0 * d + 2.0 ; }
Avec « void f( double const& ) ». Puis sans le const sur d. Les temps sont bien différents.
Aussi, bizarrement, j'ai essayé ce code avec 3 compilateurs différents et jamais la version const n'a gagné.
C'est très bizarre, parce qu'un de mes tests, c'était bien g++ (4.1.0) sous Linux. Sur un PC donc, et où je m'attendrais à exactement les mêmes résultats que sous Windows. Est-ce que tu es sûr 1) d'avoir compilé avec -O3, et 2) d'avoir mis f dans une unité de traduction compilée à part. (g++ inline s'il voit la définition, même si toi tu ne l'as pas démandé.)
Oui, j'ai mis la fonction f (vide) dans une unité compilée à part, et j'ai utilisé les options d'optimisation maximales des 3 compilateurs.
L'appel à f prend 80% du temps environ, c'est pour cela que VC8, qui l'a supprimée grâce à son analyse globale, est bien meilleur.
Quant à GCC, je pense que c'est par un malheureux hasard que sur ma machine la version non-const est plus rapide. Un coup d'oeil au code assembleur montre que la boucle avec le const contient 2 fois moins d'instructions, mais sur les architectures modernes moins d'instructions ne veut pas forcément dire plus rapide.
De toute façon, je crois qu'on peut bien dire que dans la plupart des programmes, la différence ne sera pas importante, et qu'on ne doit pas faire la décision d'office sur la base des performances. Si par la suite, il y a un problème de performance, et qu'on ne met pas le const d'office, on peut toujours l'ajouter, histoire de voir. Si ça rapporte, on le laisse (avec un commentaire). Sinon, le coût de l'essai a quand même était minimal. (Moins même que d'essayer avec f() inline.)
Oui, et on peut aussi dire qu'un bon compilateur/optimisateur vaut mieux que mille consts.
-- Sylvain Togni
Jean-Marc Bourguet
Sylvain Togni <"sylvain.togni at visionobjects.com"> writes:
Quant à GCC, je pense que c'est par un malheureux hasard que sur ma machine la version non-const est plus rapide. Un coup d'oeil au code assembleur montre que la boucle avec le const contient 2 fois moins d'instructions, mais sur les architectures modernes moins d'instructions ne veut pas forcément dire plus rapide.
Voir -mtune, -march
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
Sylvain Togni <"sylvain.togni at visionobjects.com"> writes:
Quant à GCC, je pense que c'est par un malheureux hasard que
sur ma machine la version non-const est plus rapide. Un coup
d'oeil au code assembleur montre que la boucle avec le const
contient 2 fois moins d'instructions, mais sur les
architectures modernes moins d'instructions ne veut pas
forcément dire plus rapide.
Voir -mtune, -march
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
Sylvain Togni <"sylvain.togni at visionobjects.com"> writes:
Quant à GCC, je pense que c'est par un malheureux hasard que sur ma machine la version non-const est plus rapide. Un coup d'oeil au code assembleur montre que la boucle avec le const contient 2 fois moins d'instructions, mais sur les architectures modernes moins d'instructions ne veut pas forcément dire plus rapide.
Voir -mtune, -march
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
Gabriel Dos Reis
"" writes:
| Bonsoir, | | Est-on assuré que les éléments d'un std::vector se suivent en mémoire?
Oui.
-- Gaby
"hyronn@gmail.com" <hyronn@gmail.com> writes:
| Bonsoir,
|
| Est-on assuré que les éléments d'un std::vector se suivent en mémoire?