http://www.research.att.com/~bs/esc99.html
Même si le domaine visé est l'embarqué,
le côté didactique de BS est toujours
agréable à lire...
http://www.research.att.com/~bs/esc99.html
Même si le domaine visé est l'embarqué,
le côté didactique de BS est toujours
agréable à lire...
http://www.research.att.com/~bs/esc99.html
Même si le domaine visé est l'embarqué,
le côté didactique de BS est toujours
agréable à lire...
Stan wrote:http://www.research.att.com/~bs/esc99.html
Même si le domaine visé est l'embarqué,
le côté didactique de BS est toujours
agréable à lire...
Les temps qu'il donne pour les appels de fonctions souligne qqchose que
j'avais deja remarque il y a qqtemps: les appels virtuels (ou via des
pointeurs de fonction) sont plus rapide que des appels directs. Mais je
pense que ces resultats sont biaises.
Stan wrote:
http://www.research.att.com/~bs/esc99.html
Même si le domaine visé est l'embarqué,
le côté didactique de BS est toujours
agréable à lire...
Les temps qu'il donne pour les appels de fonctions souligne qqchose que
j'avais deja remarque il y a qqtemps: les appels virtuels (ou via des
pointeurs de fonction) sont plus rapide que des appels directs. Mais je
pense que ces resultats sont biaises.
Stan wrote:http://www.research.att.com/~bs/esc99.html
Même si le domaine visé est l'embarqué,
le côté didactique de BS est toujours
agréable à lire...
Les temps qu'il donne pour les appels de fonctions souligne qqchose que
j'avais deja remarque il y a qqtemps: les appels virtuels (ou via des
pointeurs de fonction) sont plus rapide que des appels directs. Mais je
pense que ces resultats sont biaises.
Stan wrote:http://www.research.att.com/~bs/esc99.html
Même si le domaine visé est l'embarqué, le côté didactique
de BS est toujours agréable à lire...
Les temps qu'il donne pour les appels de fonctions souligne
qqchose que j'avais deja remarque il y a qqtemps: les appels
virtuels (ou via des pointeurs de fonction) sont plus rapide
que des appels directs. Mais je pense que ces resultats sont
biaises.
Stan wrote:
http://www.research.att.com/~bs/esc99.html
Même si le domaine visé est l'embarqué, le côté didactique
de BS est toujours agréable à lire...
Les temps qu'il donne pour les appels de fonctions souligne
qqchose que j'avais deja remarque il y a qqtemps: les appels
virtuels (ou via des pointeurs de fonction) sont plus rapide
que des appels directs. Mais je pense que ces resultats sont
biaises.
Stan wrote:http://www.research.att.com/~bs/esc99.html
Même si le domaine visé est l'embarqué, le côté didactique
de BS est toujours agréable à lire...
Les temps qu'il donne pour les appels de fonctions souligne
qqchose que j'avais deja remarque il y a qqtemps: les appels
virtuels (ou via des pointeurs de fonction) sont plus rapide
que des appels directs. Mais je pense que ces resultats sont
biaises.
Laurent Deniau wrote:Stan wrote:http://www.research.att.com/~bs/esc99.htmlMême si le domaine visé est l'embarqué, le côté didactique
de BS est toujours agréable à lire...Les temps qu'il donne pour les appels de fonctions souligne
qqchose que j'avais deja remarque il y a qqtemps: les appels
virtuels (ou via des pointeurs de fonction) sont plus rapide
que des appels directs. Mais je pense que ces resultats sont
biaises.
Ou qu'il s'est simplement trompé en copiant quelque chose ?
Si on ne régarde que la page postée, on se pose réelement des
questions. Littéralement, ce qu'il a écrit, c'est qu'un appel
virtuel prend 1,47 *sécondes* -- ce qui est inconcevable, même
sur la machine la plus lente que je n'ai jamais vu. Il a donné
un link à une page où il explique comment il a fait des mésures,
mais je ne trouve aucun chiffre là qui correspond à ce 1,47. En
revanche, il y a un tableau sur cette page aussi, avec ici en
plus des informations importantes comme le nombre d'itérations
et le code réelement testé.
Alors, un premier commentaire s'imposent : Dans le tableau
initial, il cite des temps pour "non-virtual member" : "p->f(1)"
et "virtual member" : "p->g(1)". Noms qu'on rétrouve sur la page
détaillée. Seulement, si on régarde le code, c'est f qui est
virtuel, et g qui ne l'est pas. Plutôt que du biais
intentionnel, je pencherais pour une simple erreur
Ensuite, il faut reconnaître que mésurer des valeurs aussi
petites relève de la défie. Chez moi, par exemple, j'ai un test
qui mésure 1) un appel de fonction inline, 2) un appel non
inline, 3) un appel membre inline, 4) un appel membre non
inline, et 5) un appel virtuel, j'ai :
avec g++ (-O3) :
Testing Inline (1000000000 iterations)...
0.00281 microseconds per iteration
Testing Out of line (1000000000 iterations)...
0.00354 microseconds per iteration
Testing Inline member (1000000000 iterations)...
0.00259 microseconds per iteration
Testing Out of line member (1000000000 iterations)...
0.00131 microseconds per iteration
Testing Virtual (1000000000 iterations)...
0.07121 microseconds per iteration
avec Sun CC (-O4) :
Testing Inline (1000000000 iterations)...
0.00223 microseconds per iteration
Testing Out of line (1000000000 iterations)...
0.0116 microseconds per iteration
Testing Inline member (1000000000 iterations)...
0.00218 microseconds per iteration
Testing Out of line member (1000000000 iterations)...
0.0159 microseconds per iteration
Testing Virtual (1000000000 iterations)...
0.06582 microseconds per iteration
Mais pour être honnête, je ne crois pas trop les mésures
inférieur à une dizaine de nanosécondes par itération. À mon
avis, les différences à ce niveau relèvent autant des variations
naturelles (le « jitter ») que des différences réeles.
Toujours est-il que je crois qu'on peut dire qu'un appel virtuel
prend entre 60 et 75 nanosécondes, qu'un appel non-virtuel
prend probablement aux alentours de 10 ou 15 nanosécondes, et
que g++ est devenu plus intelligent que mon harnès de test, et
qu'il a réussi à implémenter inline des fonctions que je voulais
non-inline (et que j'avais mis dans une source à part, exprès
pour empêcher l'optimisation).
Je dirais que la différence entre virtuel et non-virtuel
(facteur 5), c'est à peu près ce à laquelle je m'attendrais sur
Laurent Deniau wrote:
Stan wrote:
http://www.research.att.com/~bs/esc99.html
Même si le domaine visé est l'embarqué, le côté didactique
de BS est toujours agréable à lire...
Les temps qu'il donne pour les appels de fonctions souligne
qqchose que j'avais deja remarque il y a qqtemps: les appels
virtuels (ou via des pointeurs de fonction) sont plus rapide
que des appels directs. Mais je pense que ces resultats sont
biaises.
Ou qu'il s'est simplement trompé en copiant quelque chose ?
Si on ne régarde que la page postée, on se pose réelement des
questions. Littéralement, ce qu'il a écrit, c'est qu'un appel
virtuel prend 1,47 *sécondes* -- ce qui est inconcevable, même
sur la machine la plus lente que je n'ai jamais vu. Il a donné
un link à une page où il explique comment il a fait des mésures,
mais je ne trouve aucun chiffre là qui correspond à ce 1,47. En
revanche, il y a un tableau sur cette page aussi, avec ici en
plus des informations importantes comme le nombre d'itérations
et le code réelement testé.
Alors, un premier commentaire s'imposent : Dans le tableau
initial, il cite des temps pour "non-virtual member" : "p->f(1)"
et "virtual member" : "p->g(1)". Noms qu'on rétrouve sur la page
détaillée. Seulement, si on régarde le code, c'est f qui est
virtuel, et g qui ne l'est pas. Plutôt que du biais
intentionnel, je pencherais pour une simple erreur
Ensuite, il faut reconnaître que mésurer des valeurs aussi
petites relève de la défie. Chez moi, par exemple, j'ai un test
qui mésure 1) un appel de fonction inline, 2) un appel non
inline, 3) un appel membre inline, 4) un appel membre non
inline, et 5) un appel virtuel, j'ai :
avec g++ (-O3) :
Testing Inline (1000000000 iterations)...
0.00281 microseconds per iteration
Testing Out of line (1000000000 iterations)...
0.00354 microseconds per iteration
Testing Inline member (1000000000 iterations)...
0.00259 microseconds per iteration
Testing Out of line member (1000000000 iterations)...
0.00131 microseconds per iteration
Testing Virtual (1000000000 iterations)...
0.07121 microseconds per iteration
avec Sun CC (-O4) :
Testing Inline (1000000000 iterations)...
0.00223 microseconds per iteration
Testing Out of line (1000000000 iterations)...
0.0116 microseconds per iteration
Testing Inline member (1000000000 iterations)...
0.00218 microseconds per iteration
Testing Out of line member (1000000000 iterations)...
0.0159 microseconds per iteration
Testing Virtual (1000000000 iterations)...
0.06582 microseconds per iteration
Mais pour être honnête, je ne crois pas trop les mésures
inférieur à une dizaine de nanosécondes par itération. À mon
avis, les différences à ce niveau relèvent autant des variations
naturelles (le « jitter ») que des différences réeles.
Toujours est-il que je crois qu'on peut dire qu'un appel virtuel
prend entre 60 et 75 nanosécondes, qu'un appel non-virtuel
prend probablement aux alentours de 10 ou 15 nanosécondes, et
que g++ est devenu plus intelligent que mon harnès de test, et
qu'il a réussi à implémenter inline des fonctions que je voulais
non-inline (et que j'avais mis dans une source à part, exprès
pour empêcher l'optimisation).
Je dirais que la différence entre virtuel et non-virtuel
(facteur 5), c'est à peu près ce à laquelle je m'attendrais sur
Laurent Deniau wrote:Stan wrote:http://www.research.att.com/~bs/esc99.htmlMême si le domaine visé est l'embarqué, le côté didactique
de BS est toujours agréable à lire...Les temps qu'il donne pour les appels de fonctions souligne
qqchose que j'avais deja remarque il y a qqtemps: les appels
virtuels (ou via des pointeurs de fonction) sont plus rapide
que des appels directs. Mais je pense que ces resultats sont
biaises.
Ou qu'il s'est simplement trompé en copiant quelque chose ?
Si on ne régarde que la page postée, on se pose réelement des
questions. Littéralement, ce qu'il a écrit, c'est qu'un appel
virtuel prend 1,47 *sécondes* -- ce qui est inconcevable, même
sur la machine la plus lente que je n'ai jamais vu. Il a donné
un link à une page où il explique comment il a fait des mésures,
mais je ne trouve aucun chiffre là qui correspond à ce 1,47. En
revanche, il y a un tableau sur cette page aussi, avec ici en
plus des informations importantes comme le nombre d'itérations
et le code réelement testé.
Alors, un premier commentaire s'imposent : Dans le tableau
initial, il cite des temps pour "non-virtual member" : "p->f(1)"
et "virtual member" : "p->g(1)". Noms qu'on rétrouve sur la page
détaillée. Seulement, si on régarde le code, c'est f qui est
virtuel, et g qui ne l'est pas. Plutôt que du biais
intentionnel, je pencherais pour une simple erreur
Ensuite, il faut reconnaître que mésurer des valeurs aussi
petites relève de la défie. Chez moi, par exemple, j'ai un test
qui mésure 1) un appel de fonction inline, 2) un appel non
inline, 3) un appel membre inline, 4) un appel membre non
inline, et 5) un appel virtuel, j'ai :
avec g++ (-O3) :
Testing Inline (1000000000 iterations)...
0.00281 microseconds per iteration
Testing Out of line (1000000000 iterations)...
0.00354 microseconds per iteration
Testing Inline member (1000000000 iterations)...
0.00259 microseconds per iteration
Testing Out of line member (1000000000 iterations)...
0.00131 microseconds per iteration
Testing Virtual (1000000000 iterations)...
0.07121 microseconds per iteration
avec Sun CC (-O4) :
Testing Inline (1000000000 iterations)...
0.00223 microseconds per iteration
Testing Out of line (1000000000 iterations)...
0.0116 microseconds per iteration
Testing Inline member (1000000000 iterations)...
0.00218 microseconds per iteration
Testing Out of line member (1000000000 iterations)...
0.0159 microseconds per iteration
Testing Virtual (1000000000 iterations)...
0.06582 microseconds per iteration
Mais pour être honnête, je ne crois pas trop les mésures
inférieur à une dizaine de nanosécondes par itération. À mon
avis, les différences à ce niveau relèvent autant des variations
naturelles (le « jitter ») que des différences réeles.
Toujours est-il que je crois qu'on peut dire qu'un appel virtuel
prend entre 60 et 75 nanosécondes, qu'un appel non-virtuel
prend probablement aux alentours de 10 ou 15 nanosécondes, et
que g++ est devenu plus intelligent que mon harnès de test, et
qu'il a réussi à implémenter inline des fonctions que je voulais
non-inline (et que j'avais mis dans une source à part, exprès
pour empêcher l'optimisation).
Je dirais que la différence entre virtuel et non-virtuel
(facteur 5), c'est à peu près ce à laquelle je m'attendrais sur
Stan wrote:http://www.research.att.com/~bs/esc99.html
Même si le domaine visé est l'embarqué,
le côté didactique de BS est toujours
agréable à lire...
Les temps qu'il donne pour les appels de fonctions souligne qqchose que
j'avais deja remarque il y a qqtemps: les appels virtuels (ou via des
pointeurs de fonction) sont plus rapide que des appels directs. Mais je
pense que ces resultats sont biaises.
Stan wrote:
http://www.research.att.com/~bs/esc99.html
Même si le domaine visé est l'embarqué,
le côté didactique de BS est toujours
agréable à lire...
Les temps qu'il donne pour les appels de fonctions souligne qqchose que
j'avais deja remarque il y a qqtemps: les appels virtuels (ou via des
pointeurs de fonction) sont plus rapide que des appels directs. Mais je
pense que ces resultats sont biaises.
Stan wrote:http://www.research.att.com/~bs/esc99.html
Même si le domaine visé est l'embarqué,
le côté didactique de BS est toujours
agréable à lire...
Les temps qu'il donne pour les appels de fonctions souligne qqchose que
j'avais deja remarque il y a qqtemps: les appels virtuels (ou via des
pointeurs de fonction) sont plus rapide que des appels directs. Mais je
pense que ces resultats sont biaises.
Laurent Deniau writes:Stan wrote:http://www.research.att.com/~bs/esc99.html
Même si le domaine visé est l'embarqué,
le côté didactique de BS est toujours
agréable à lire...
Les temps qu'il donne pour les appels de fonctions souligne qqchose que
j'avais deja remarque il y a qqtemps: les appels virtuels (ou via des
pointeurs de fonction) sont plus rapide que des appels directs. Mais je
pense que ces resultats sont biaises.
Je pense que pour les processeurs actuels (pipeline profond,
multiple instructions commencées/terminées dans le même
cycle, exécution dans le désordre, exécution spéculative,
prédiction des sauts conditionnels, prédictions des
adresses, deux ou trois niveaux de cache) essayer de mesurer
quelque chose de ce genre n'a plus de sens.
Laurent Deniau <Laurent.Deniau@cern.ch> writes:
Stan wrote:
http://www.research.att.com/~bs/esc99.html
Même si le domaine visé est l'embarqué,
le côté didactique de BS est toujours
agréable à lire...
Les temps qu'il donne pour les appels de fonctions souligne qqchose que
j'avais deja remarque il y a qqtemps: les appels virtuels (ou via des
pointeurs de fonction) sont plus rapide que des appels directs. Mais je
pense que ces resultats sont biaises.
Je pense que pour les processeurs actuels (pipeline profond,
multiple instructions commencées/terminées dans le même
cycle, exécution dans le désordre, exécution spéculative,
prédiction des sauts conditionnels, prédictions des
adresses, deux ou trois niveaux de cache) essayer de mesurer
quelque chose de ce genre n'a plus de sens.
Laurent Deniau writes:Stan wrote:http://www.research.att.com/~bs/esc99.html
Même si le domaine visé est l'embarqué,
le côté didactique de BS est toujours
agréable à lire...
Les temps qu'il donne pour les appels de fonctions souligne qqchose que
j'avais deja remarque il y a qqtemps: les appels virtuels (ou via des
pointeurs de fonction) sont plus rapide que des appels directs. Mais je
pense que ces resultats sont biaises.
Je pense que pour les processeurs actuels (pipeline profond,
multiple instructions commencées/terminées dans le même
cycle, exécution dans le désordre, exécution spéculative,
prédiction des sauts conditionnels, prédictions des
adresses, deux ou trois niveaux de cache) essayer de mesurer
quelque chose de ce genre n'a plus de sens.
wrote:Laurent Deniau wrote:
Ensuite, il faut reconnaître que mésurer des valeurs aussi
petites relève de la défie. Chez moi, par exemple, j'ai un
test qui mésure 1) un appel de fonction inline, 2) un appel
non inline, 3) un appel membre inline, 4) un appel membre
non inline, et 5) un appel virtuel, j'ai :
avec g++ (-O3) :
Testing Inline (1000000000 iterations)...
0.00281 microseconds per iteration
Testing Out of line (1000000000 iterations)...
0.00354 microseconds per iteration
Testing Inline member (1000000000 iterations)...
0.00259 microseconds per iteration
Testing Out of line member (1000000000 iterations)...
0.00131 microseconds per iteration
Testing Virtual (1000000000 iterations)...
0.07121 microseconds per iteration
avec Sun CC (-O4) :
Testing Inline (1000000000 iterations)...
0.00223 microseconds per iteration
Testing Out of line (1000000000 iterations)...
0.0116 microseconds per iteration
Testing Inline member (1000000000 iterations)...
0.00218 microseconds per iteration
Testing Out of line member (1000000000 iterations)...
0.0159 microseconds per iteration
Testing Virtual (1000000000 iterations)...
0.06582 microseconds per iteration
Mais pour être honnête, je ne crois pas trop les mésures
inférieur à une dizaine de nanosécondes par itération. À mon
Pourquoi du moment qu'elles sont mesurees sur une duree
significative?
avis, les différences à ce niveau relèvent autant des
variations naturelles (le « jitter ») que des différences
réeles.
Qu'est ce que tu entends par la?
Toujours est-il que je crois qu'on peut dire qu'un appel
virtuel prend entre 60 et 75 nanosécondes, qu'un appel
non-virtuel
Les temps absolus sont peut parlant (depends des architectures
et des compilateurs). Je prefere de loin un ratio
virtuel/non-virtuel.
prend probablement aux alentours de 10 ou 15 nanosécondes,
et que g++ est devenu plus intelligent que mon harnès de
test, et qu'il a réussi à implémenter inline des fonctions
que je voulais non-inline (et que j'avais mis dans une
source à part, exprès pour empêcher l'optimisation).
Je dirais que la différence entre virtuel et non-virtuel
(facteur 5), c'est à peu près ce à laquelle je m'attendrais
sur
Je n'ai jamais vu un facteur 5. J'ai vu -10%/+50% au maximum.
Et c'est coherent avec un appel indirect de fonction via un
pointeur.
Au passage j'ai une implementation de message dispatch en C
(type Objective-C) qui a un overhead de 40% a 80% par rapport
a un appel direct.
Et c'est forcement plus lent qu'un method lookup. Alors j'ai
du mal a imaginer un facteur 5 pour les methodes virtuelles.
Tu ne comparais pas avec de l'inline par harsard?
kanze@gabi-soft.fr wrote:
Laurent Deniau wrote:
Ensuite, il faut reconnaître que mésurer des valeurs aussi
petites relève de la défie. Chez moi, par exemple, j'ai un
test qui mésure 1) un appel de fonction inline, 2) un appel
non inline, 3) un appel membre inline, 4) un appel membre
non inline, et 5) un appel virtuel, j'ai :
avec g++ (-O3) :
Testing Inline (1000000000 iterations)...
0.00281 microseconds per iteration
Testing Out of line (1000000000 iterations)...
0.00354 microseconds per iteration
Testing Inline member (1000000000 iterations)...
0.00259 microseconds per iteration
Testing Out of line member (1000000000 iterations)...
0.00131 microseconds per iteration
Testing Virtual (1000000000 iterations)...
0.07121 microseconds per iteration
avec Sun CC (-O4) :
Testing Inline (1000000000 iterations)...
0.00223 microseconds per iteration
Testing Out of line (1000000000 iterations)...
0.0116 microseconds per iteration
Testing Inline member (1000000000 iterations)...
0.00218 microseconds per iteration
Testing Out of line member (1000000000 iterations)...
0.0159 microseconds per iteration
Testing Virtual (1000000000 iterations)...
0.06582 microseconds per iteration
Mais pour être honnête, je ne crois pas trop les mésures
inférieur à une dizaine de nanosécondes par itération. À mon
Pourquoi du moment qu'elles sont mesurees sur une duree
significative?
avis, les différences à ce niveau relèvent autant des
variations naturelles (le « jitter ») que des différences
réeles.
Qu'est ce que tu entends par la?
Toujours est-il que je crois qu'on peut dire qu'un appel
virtuel prend entre 60 et 75 nanosécondes, qu'un appel
non-virtuel
Les temps absolus sont peut parlant (depends des architectures
et des compilateurs). Je prefere de loin un ratio
virtuel/non-virtuel.
prend probablement aux alentours de 10 ou 15 nanosécondes,
et que g++ est devenu plus intelligent que mon harnès de
test, et qu'il a réussi à implémenter inline des fonctions
que je voulais non-inline (et que j'avais mis dans une
source à part, exprès pour empêcher l'optimisation).
Je dirais que la différence entre virtuel et non-virtuel
(facteur 5), c'est à peu près ce à laquelle je m'attendrais
sur
Je n'ai jamais vu un facteur 5. J'ai vu -10%/+50% au maximum.
Et c'est coherent avec un appel indirect de fonction via un
pointeur.
Au passage j'ai une implementation de message dispatch en C
(type Objective-C) qui a un overhead de 40% a 80% par rapport
a un appel direct.
Et c'est forcement plus lent qu'un method lookup. Alors j'ai
du mal a imaginer un facteur 5 pour les methodes virtuelles.
Tu ne comparais pas avec de l'inline par harsard?
wrote:Laurent Deniau wrote:
Ensuite, il faut reconnaître que mésurer des valeurs aussi
petites relève de la défie. Chez moi, par exemple, j'ai un
test qui mésure 1) un appel de fonction inline, 2) un appel
non inline, 3) un appel membre inline, 4) un appel membre
non inline, et 5) un appel virtuel, j'ai :
avec g++ (-O3) :
Testing Inline (1000000000 iterations)...
0.00281 microseconds per iteration
Testing Out of line (1000000000 iterations)...
0.00354 microseconds per iteration
Testing Inline member (1000000000 iterations)...
0.00259 microseconds per iteration
Testing Out of line member (1000000000 iterations)...
0.00131 microseconds per iteration
Testing Virtual (1000000000 iterations)...
0.07121 microseconds per iteration
avec Sun CC (-O4) :
Testing Inline (1000000000 iterations)...
0.00223 microseconds per iteration
Testing Out of line (1000000000 iterations)...
0.0116 microseconds per iteration
Testing Inline member (1000000000 iterations)...
0.00218 microseconds per iteration
Testing Out of line member (1000000000 iterations)...
0.0159 microseconds per iteration
Testing Virtual (1000000000 iterations)...
0.06582 microseconds per iteration
Mais pour être honnête, je ne crois pas trop les mésures
inférieur à une dizaine de nanosécondes par itération. À mon
Pourquoi du moment qu'elles sont mesurees sur une duree
significative?
avis, les différences à ce niveau relèvent autant des
variations naturelles (le « jitter ») que des différences
réeles.
Qu'est ce que tu entends par la?
Toujours est-il que je crois qu'on peut dire qu'un appel
virtuel prend entre 60 et 75 nanosécondes, qu'un appel
non-virtuel
Les temps absolus sont peut parlant (depends des architectures
et des compilateurs). Je prefere de loin un ratio
virtuel/non-virtuel.
prend probablement aux alentours de 10 ou 15 nanosécondes,
et que g++ est devenu plus intelligent que mon harnès de
test, et qu'il a réussi à implémenter inline des fonctions
que je voulais non-inline (et que j'avais mis dans une
source à part, exprès pour empêcher l'optimisation).
Je dirais que la différence entre virtuel et non-virtuel
(facteur 5), c'est à peu près ce à laquelle je m'attendrais
sur
Je n'ai jamais vu un facteur 5. J'ai vu -10%/+50% au maximum.
Et c'est coherent avec un appel indirect de fonction via un
pointeur.
Au passage j'ai une implementation de message dispatch en C
(type Objective-C) qui a un overhead de 40% a 80% par rapport
a un appel direct.
Et c'est forcement plus lent qu'un method lookup. Alors j'ai
du mal a imaginer un facteur 5 pour les methodes virtuelles.
Tu ne comparais pas avec de l'inline par harsard?
Mais pour être honnête, je ne crois pas trop les mésures
inférieur à une dizaine de nanosécondes par itération. À monPourquoi du moment qu'elles sont mesurees sur une duree
significative?
Parce que je constate qu'elles varient d'une exécution à
l'autre. Et que du fait que mon compteur de boucle est surn un
entier 32 bits, je ne peux pas augmenter la durée de façon
illimitée. (Normallement, je considère quelque chose comme cinq
minutes pour chaque mésure comme un minimum. Mais ici, j'en suis
loin.)
avis, les différences à ce niveau relèvent autant des
variations naturelles (le « jitter ») que des différences
réeles.Qu'est ce que tu entends par la?
Le « jitter », c'est les petites variations dans les mésures
d'une mésure à l'autre.
Toujours est-il que je crois qu'on peut dire qu'un appel
virtuel prend entre 60 et 75 nanosécondes, qu'un appel
non-virtuelLes temps absolus sont peut parlant (depends des architectures
et des compilateurs). Je prefere de loin un ratio
virtuel/non-virtuel.
Mais ça aussi dépend de l'architectures et des compilateurs. Et
beaucoup. Disons que sur une machine généraliste moderne, je
m'attendrais à un rapport entre 1:2 et 1:10. Sur des machines
plus primitives (embarquées ou anciennes), j'ai déjà vu
nettement moins de 1:2.
prend probablement aux alentours de 10 ou 15 nanosécondes,
et que g++ est devenu plus intelligent que mon harnès de
test, et qu'il a réussi à implémenter inline des fonctions
que je voulais non-inline (et que j'avais mis dans une
source à part, exprès pour empêcher l'optimisation).
Je dirais que la différence entre virtuel et non-virtuel
(facteur 5), c'est à peu près ce à laquelle je m'attendrais
surJe n'ai jamais vu un facteur 5. J'ai vu -10%/+50% au maximum.
Et c'est coherent avec un appel indirect de fonction via un
pointeur.
On est déjà à plus de quatre ci-dessus, sur un Sparc plutôt
ancien. Des personnes de chez HP (à l'époque) m'ont assuré que
sur l'architecture PA Risc, c'était pire.
Le problème, c'est que c'est un branchement indirect. Ce qui
pose des problèmes pour la prédiction des branchements. Dans le
cas du HP, d'après ce que j'ai compris, il en résulte un flush
du pipeline à chaque coup.
Note que je ne mésure que le coup de l'appel d'une fonction
triviale (qui renvoie un int constante) : « i = f() ; ». Il y a
donc non seulement l'appel de la fonction proprement dit, mais
aussi chargement du pointeur this, chargement et affectation de
la valeur de retour, et le retour lui-même. La différence dans
le temps de l'appel lui-même est donc encore plus grande.
De l'autre côté, il faut le comparer à ce qu'on fait dans la
fonction. Dès qu'il y a une multiplication ou une division
entière, avec des termes non constantes, le temps de l'appel
devient négligeable. Sur ma machine... on ne peut pas faire de
généralités.
Au passage j'ai une implementation de message dispatch en C
(type Objective-C) qui a un overhead de 40% a 80% par rapport
a un appel direct.
Sur quelle machine ? Mésuré comment ?
Et c'est forcement plus lent qu'un method lookup. Alors j'ai
du mal a imaginer un facteur 5 pour les methodes virtuelles.
C'est cependant le cas, au moins sur les machines modernes.
Tu ne comparais pas avec de l'inline par harsard?
Est-ce que tu as au moins lu ce que j'ai posté ? J'ai fait
plusieurs mésures, dans des conditions différentes. J'ai bien
l'impression que g++ a inliné les fonctions, parce qu'il n'y a
pas de différences entre les temps pour les fonctions inlinées,
et les temps pour les fonctions non-virtuelles. Et que ces temps
pour les fonctions inlinées ressemblent à peu près à celles de
Sun CC. Dans le cas de Sun CC, en revanche, il y a bien une
différence.
Mais pour être honnête, je ne crois pas trop les mésures
inférieur à une dizaine de nanosécondes par itération. À mon
Pourquoi du moment qu'elles sont mesurees sur une duree
significative?
Parce que je constate qu'elles varient d'une exécution à
l'autre. Et que du fait que mon compteur de boucle est surn un
entier 32 bits, je ne peux pas augmenter la durée de façon
illimitée. (Normallement, je considère quelque chose comme cinq
minutes pour chaque mésure comme un minimum. Mais ici, j'en suis
loin.)
avis, les différences à ce niveau relèvent autant des
variations naturelles (le « jitter ») que des différences
réeles.
Qu'est ce que tu entends par la?
Le « jitter », c'est les petites variations dans les mésures
d'une mésure à l'autre.
Toujours est-il que je crois qu'on peut dire qu'un appel
virtuel prend entre 60 et 75 nanosécondes, qu'un appel
non-virtuel
Les temps absolus sont peut parlant (depends des architectures
et des compilateurs). Je prefere de loin un ratio
virtuel/non-virtuel.
Mais ça aussi dépend de l'architectures et des compilateurs. Et
beaucoup. Disons que sur une machine généraliste moderne, je
m'attendrais à un rapport entre 1:2 et 1:10. Sur des machines
plus primitives (embarquées ou anciennes), j'ai déjà vu
nettement moins de 1:2.
prend probablement aux alentours de 10 ou 15 nanosécondes,
et que g++ est devenu plus intelligent que mon harnès de
test, et qu'il a réussi à implémenter inline des fonctions
que je voulais non-inline (et que j'avais mis dans une
source à part, exprès pour empêcher l'optimisation).
Je dirais que la différence entre virtuel et non-virtuel
(facteur 5), c'est à peu près ce à laquelle je m'attendrais
sur
Je n'ai jamais vu un facteur 5. J'ai vu -10%/+50% au maximum.
Et c'est coherent avec un appel indirect de fonction via un
pointeur.
On est déjà à plus de quatre ci-dessus, sur un Sparc plutôt
ancien. Des personnes de chez HP (à l'époque) m'ont assuré que
sur l'architecture PA Risc, c'était pire.
Le problème, c'est que c'est un branchement indirect. Ce qui
pose des problèmes pour la prédiction des branchements. Dans le
cas du HP, d'après ce que j'ai compris, il en résulte un flush
du pipeline à chaque coup.
Note que je ne mésure que le coup de l'appel d'une fonction
triviale (qui renvoie un int constante) : « i = f() ; ». Il y a
donc non seulement l'appel de la fonction proprement dit, mais
aussi chargement du pointeur this, chargement et affectation de
la valeur de retour, et le retour lui-même. La différence dans
le temps de l'appel lui-même est donc encore plus grande.
De l'autre côté, il faut le comparer à ce qu'on fait dans la
fonction. Dès qu'il y a une multiplication ou une division
entière, avec des termes non constantes, le temps de l'appel
devient négligeable. Sur ma machine... on ne peut pas faire de
généralités.
Au passage j'ai une implementation de message dispatch en C
(type Objective-C) qui a un overhead de 40% a 80% par rapport
a un appel direct.
Sur quelle machine ? Mésuré comment ?
Et c'est forcement plus lent qu'un method lookup. Alors j'ai
du mal a imaginer un facteur 5 pour les methodes virtuelles.
C'est cependant le cas, au moins sur les machines modernes.
Tu ne comparais pas avec de l'inline par harsard?
Est-ce que tu as au moins lu ce que j'ai posté ? J'ai fait
plusieurs mésures, dans des conditions différentes. J'ai bien
l'impression que g++ a inliné les fonctions, parce qu'il n'y a
pas de différences entre les temps pour les fonctions inlinées,
et les temps pour les fonctions non-virtuelles. Et que ces temps
pour les fonctions inlinées ressemblent à peu près à celles de
Sun CC. Dans le cas de Sun CC, en revanche, il y a bien une
différence.
Mais pour être honnête, je ne crois pas trop les mésures
inférieur à une dizaine de nanosécondes par itération. À monPourquoi du moment qu'elles sont mesurees sur une duree
significative?
Parce que je constate qu'elles varient d'une exécution à
l'autre. Et que du fait que mon compteur de boucle est surn un
entier 32 bits, je ne peux pas augmenter la durée de façon
illimitée. (Normallement, je considère quelque chose comme cinq
minutes pour chaque mésure comme un minimum. Mais ici, j'en suis
loin.)
avis, les différences à ce niveau relèvent autant des
variations naturelles (le « jitter ») que des différences
réeles.Qu'est ce que tu entends par la?
Le « jitter », c'est les petites variations dans les mésures
d'une mésure à l'autre.
Toujours est-il que je crois qu'on peut dire qu'un appel
virtuel prend entre 60 et 75 nanosécondes, qu'un appel
non-virtuelLes temps absolus sont peut parlant (depends des architectures
et des compilateurs). Je prefere de loin un ratio
virtuel/non-virtuel.
Mais ça aussi dépend de l'architectures et des compilateurs. Et
beaucoup. Disons que sur une machine généraliste moderne, je
m'attendrais à un rapport entre 1:2 et 1:10. Sur des machines
plus primitives (embarquées ou anciennes), j'ai déjà vu
nettement moins de 1:2.
prend probablement aux alentours de 10 ou 15 nanosécondes,
et que g++ est devenu plus intelligent que mon harnès de
test, et qu'il a réussi à implémenter inline des fonctions
que je voulais non-inline (et que j'avais mis dans une
source à part, exprès pour empêcher l'optimisation).
Je dirais que la différence entre virtuel et non-virtuel
(facteur 5), c'est à peu près ce à laquelle je m'attendrais
surJe n'ai jamais vu un facteur 5. J'ai vu -10%/+50% au maximum.
Et c'est coherent avec un appel indirect de fonction via un
pointeur.
On est déjà à plus de quatre ci-dessus, sur un Sparc plutôt
ancien. Des personnes de chez HP (à l'époque) m'ont assuré que
sur l'architecture PA Risc, c'était pire.
Le problème, c'est que c'est un branchement indirect. Ce qui
pose des problèmes pour la prédiction des branchements. Dans le
cas du HP, d'après ce que j'ai compris, il en résulte un flush
du pipeline à chaque coup.
Note que je ne mésure que le coup de l'appel d'une fonction
triviale (qui renvoie un int constante) : « i = f() ; ». Il y a
donc non seulement l'appel de la fonction proprement dit, mais
aussi chargement du pointeur this, chargement et affectation de
la valeur de retour, et le retour lui-même. La différence dans
le temps de l'appel lui-même est donc encore plus grande.
De l'autre côté, il faut le comparer à ce qu'on fait dans la
fonction. Dès qu'il y a une multiplication ou une division
entière, avec des termes non constantes, le temps de l'appel
devient négligeable. Sur ma machine... on ne peut pas faire de
généralités.
Au passage j'ai une implementation de message dispatch en C
(type Objective-C) qui a un overhead de 40% a 80% par rapport
a un appel direct.
Sur quelle machine ? Mésuré comment ?
Et c'est forcement plus lent qu'un method lookup. Alors j'ai
du mal a imaginer un facteur 5 pour les methodes virtuelles.
C'est cependant le cas, au moins sur les machines modernes.
Tu ne comparais pas avec de l'inline par harsard?
Est-ce que tu as au moins lu ce que j'ai posté ? J'ai fait
plusieurs mésures, dans des conditions différentes. J'ai bien
l'impression que g++ a inliné les fonctions, parce qu'il n'y a
pas de différences entre les temps pour les fonctions inlinées,
et les temps pour les fonctions non-virtuelles. Et que ces temps
pour les fonctions inlinées ressemblent à peu près à celles de
Sun CC. Dans le cas de Sun CC, en revanche, il y a bien une
différence.
Jean-Marc Bourguet wrote:Laurent Deniau writes:Stan wrote:http://www.research.att.com/~bs/esc99.html
Même si le domaine visé est l'embarqué,
le côté didactique de BS est toujours
agréable à lire...
Les temps qu'il donne pour les appels de fonctions souligne qqchose que
j'avais deja remarque il y a qqtemps: les appels virtuels (ou via des
pointeurs de fonction) sont plus rapide que des appels directs. Mais je
pense que ces resultats sont biaises.
Je pense que pour les processeurs actuels (pipeline profond,
multiple instructions commencées/terminées dans le même
cycle, exécution dans le désordre, exécution spéculative,
prédiction des sauts conditionnels, prédictions des
adresses, deux ou trois niveaux de cache) essayer de mesurer
quelque chose de ce genre n'a plus de sens.
Pourquoi? L'experience a montre que la mesure est stable et
reproductible.
Jean-Marc Bourguet wrote:
Laurent Deniau <Laurent.Deniau@cern.ch> writes:
Stan wrote:
http://www.research.att.com/~bs/esc99.html
Même si le domaine visé est l'embarqué,
le côté didactique de BS est toujours
agréable à lire...
Les temps qu'il donne pour les appels de fonctions souligne qqchose que
j'avais deja remarque il y a qqtemps: les appels virtuels (ou via des
pointeurs de fonction) sont plus rapide que des appels directs. Mais je
pense que ces resultats sont biaises.
Je pense que pour les processeurs actuels (pipeline profond,
multiple instructions commencées/terminées dans le même
cycle, exécution dans le désordre, exécution spéculative,
prédiction des sauts conditionnels, prédictions des
adresses, deux ou trois niveaux de cache) essayer de mesurer
quelque chose de ce genre n'a plus de sens.
Pourquoi? L'experience a montre que la mesure est stable et
reproductible.
Jean-Marc Bourguet wrote:Laurent Deniau writes:Stan wrote:http://www.research.att.com/~bs/esc99.html
Même si le domaine visé est l'embarqué,
le côté didactique de BS est toujours
agréable à lire...
Les temps qu'il donne pour les appels de fonctions souligne qqchose que
j'avais deja remarque il y a qqtemps: les appels virtuels (ou via des
pointeurs de fonction) sont plus rapide que des appels directs. Mais je
pense que ces resultats sont biaises.
Je pense que pour les processeurs actuels (pipeline profond,
multiple instructions commencées/terminées dans le même
cycle, exécution dans le désordre, exécution spéculative,
prédiction des sauts conditionnels, prédictions des
adresses, deux ou trois niveaux de cache) essayer de mesurer
quelque chose de ce genre n'a plus de sens.
Pourquoi? L'experience a montre que la mesure est stable et
reproductible.
Mon idee est que maintenant essayer de separer les choses de leur
contexte n'a plus guere de sens parce que le cout depend fortement du
contexte; ca ne m'etonnerait pas du tout qu'on se retrouve meme
parfois avec des couts negatifs.
Dans le cas present, la premiere chose a noter, c'est que quand on
compile pour des objets partages (code PIC), on se retrouve souvent
(au moins sous Unix, je suppose pour Windows aussi) a ce que des
appels "directs" soient aussi en fait des appels indirects (je suppose
que B.S et toi savez ca et en avez tenu compte).
Deuxieme chose, ensuite, quels sont les facteurs qui comptent dans le
temps d'execution d'un appel?
1/ est-ce que la page est en memoire
independant de direct-indirect
2/ est-ce que l'entree de la page est dans le TLB
independant de direct-indirect
3/ est-ce que la fonction est dans le cache
independant de direct-indirect
4/ est-ce que l'appel est predictible (est-ce qu'il est pris ou non,
est-ce que sa destination est predictible ou non).
la d'accord, et c'est justement en partie ce que l'on mesure.
A mon avis ces quatres facteurs vont en pratique dominer la difference
entre un appel direct et un appel indirect et ces quatres facteurs
sont dependants du contexte.
Vu la simplicite ici si la mesure est bien faite, on ne mesurera que
le cas ou la reponse a ces quatres questions est oui. Je ne suis pas
sur que ce soit une donnee pertinente (ca neglige en particulier
l'effet qu'il est normalement plus difficile de prevoir la destination
d'un appel indirect).
J'ai ecrit si la mesure est bien faite car je suis un peu etonne que
le cas appel direct soit plus lent que le cas appel indirect et je me
demande si un facteur (le premier qui vient a l'esprit est le partage
d'une ligne de cache entre le code appelant et le code de la fonction
directe; dans ce cas le cache est recharge a chaque fois tandis que
sans partage le cache contient tout ce qui est necessaire en
permanence; mais celui-ci je suppose que tu l'as verifie) n'a pas ete
ignore. J'aurais tendance a refaire tourner ca avec un simulateur
architectural avant de deduire quoi que ce soit a ce niveau. Il y en
a un ici: http://www.simplescalar.com mais je ne l'ai jamais utilise.
Mon idee est que maintenant essayer de separer les choses de leur
contexte n'a plus guere de sens parce que le cout depend fortement du
contexte; ca ne m'etonnerait pas du tout qu'on se retrouve meme
parfois avec des couts negatifs.
Dans le cas present, la premiere chose a noter, c'est que quand on
compile pour des objets partages (code PIC), on se retrouve souvent
(au moins sous Unix, je suppose pour Windows aussi) a ce que des
appels "directs" soient aussi en fait des appels indirects (je suppose
que B.S et toi savez ca et en avez tenu compte).
Deuxieme chose, ensuite, quels sont les facteurs qui comptent dans le
temps d'execution d'un appel?
1/ est-ce que la page est en memoire
independant de direct-indirect
2/ est-ce que l'entree de la page est dans le TLB
independant de direct-indirect
3/ est-ce que la fonction est dans le cache
independant de direct-indirect
4/ est-ce que l'appel est predictible (est-ce qu'il est pris ou non,
est-ce que sa destination est predictible ou non).
la d'accord, et c'est justement en partie ce que l'on mesure.
A mon avis ces quatres facteurs vont en pratique dominer la difference
entre un appel direct et un appel indirect et ces quatres facteurs
sont dependants du contexte.
Vu la simplicite ici si la mesure est bien faite, on ne mesurera que
le cas ou la reponse a ces quatres questions est oui. Je ne suis pas
sur que ce soit une donnee pertinente (ca neglige en particulier
l'effet qu'il est normalement plus difficile de prevoir la destination
d'un appel indirect).
J'ai ecrit si la mesure est bien faite car je suis un peu etonne que
le cas appel direct soit plus lent que le cas appel indirect et je me
demande si un facteur (le premier qui vient a l'esprit est le partage
d'une ligne de cache entre le code appelant et le code de la fonction
directe; dans ce cas le cache est recharge a chaque fois tandis que
sans partage le cache contient tout ce qui est necessaire en
permanence; mais celui-ci je suppose que tu l'as verifie) n'a pas ete
ignore. J'aurais tendance a refaire tourner ca avec un simulateur
architectural avant de deduire quoi que ce soit a ce niveau. Il y en
a un ici: http://www.simplescalar.com mais je ne l'ai jamais utilise.
Mon idee est que maintenant essayer de separer les choses de leur
contexte n'a plus guere de sens parce que le cout depend fortement du
contexte; ca ne m'etonnerait pas du tout qu'on se retrouve meme
parfois avec des couts negatifs.
Dans le cas present, la premiere chose a noter, c'est que quand on
compile pour des objets partages (code PIC), on se retrouve souvent
(au moins sous Unix, je suppose pour Windows aussi) a ce que des
appels "directs" soient aussi en fait des appels indirects (je suppose
que B.S et toi savez ca et en avez tenu compte).
Deuxieme chose, ensuite, quels sont les facteurs qui comptent dans le
temps d'execution d'un appel?
1/ est-ce que la page est en memoire
independant de direct-indirect
2/ est-ce que l'entree de la page est dans le TLB
independant de direct-indirect
3/ est-ce que la fonction est dans le cache
independant de direct-indirect
4/ est-ce que l'appel est predictible (est-ce qu'il est pris ou non,
est-ce que sa destination est predictible ou non).
la d'accord, et c'est justement en partie ce que l'on mesure.
A mon avis ces quatres facteurs vont en pratique dominer la difference
entre un appel direct et un appel indirect et ces quatres facteurs
sont dependants du contexte.
Vu la simplicite ici si la mesure est bien faite, on ne mesurera que
le cas ou la reponse a ces quatres questions est oui. Je ne suis pas
sur que ce soit une donnee pertinente (ca neglige en particulier
l'effet qu'il est normalement plus difficile de prevoir la destination
d'un appel indirect).
J'ai ecrit si la mesure est bien faite car je suis un peu etonne que
le cas appel direct soit plus lent que le cas appel indirect et je me
demande si un facteur (le premier qui vient a l'esprit est le partage
d'une ligne de cache entre le code appelant et le code de la fonction
directe; dans ce cas le cache est recharge a chaque fois tandis que
sans partage le cache contient tout ce qui est necessaire en
permanence; mais celui-ci je suppose que tu l'as verifie) n'a pas ete
ignore. J'aurais tendance a refaire tourner ca avec un simulateur
architectural avant de deduire quoi que ce soit a ce niveau. Il y en
a un ici: http://www.simplescalar.com mais je ne l'ai jamais utilise.