void f(int val) vs void f(int & val)

void f(int val) vs void f(int & val) - C++ - Programmation

Marsh Posté le 04-11-2009 à 23:20:38    

salut,
 
en terme de perf le fait de passer des types de base par référence est-il plus lent que de les passer par valeur ou cela revient il exactement au même ?
 
merci


---------------
.
Reply

Marsh Posté le 04-11-2009 à 23:20:38   

Reply

Marsh Posté le 05-11-2009 à 06:54:02    

par référence ou par référence constante. La ton exemple est foireux car la sémantique de la fonction change.

Reply

Marsh Posté le 05-11-2009 à 07:40:37    

disons les deux cas, par rapport à un passage par référence et par rapport à un passage par référence constante


---------------
.
Reply

Marsh Posté le 05-11-2009 à 12:54:01    

Si ce que tu veux comme cas d'utilisation, c'est du void f(int val), le passage par valeur sera plus économique.
 

Maintenant je dirais (probablement mal):
A partir du moment où tu as une référence, la logique voudrait que le compilo déréférence la référence a chaque utilisation car l'objet référencé peut avoir changé (bon à voir peut être avec volatile).
 
void f(int val)
{
  while (val)
  {
     poulpe();
     --val;
  }
}
 
void f(int &val)
{
  while (val)
  {
     poulpe(); // poulpe peut avoir changé le int  
     --val;
  }
}
 
Maintenant je sais pas si c'est une remarque à la con. (et que le compilo n'optimisera pas que si y'a un volatile en plus :D)

edit: je me suis pris les pieds dans le tapis en voulant faire une démo foireuse >> seek coffee.
 
Mais si tu cherche les perfs, à partir du moment où le type rentre dans un registre du cpu (ou plusieurs de manière efficace) c'est int ou const int (le const permettant entre autre au niveau optimisation de garantir que l'appelé ne modifia pas le registre utilisé pour le passage).
 
Enfin je dis ça comme ça moa.


Message édité par bjone le 05-11-2009 à 13:11:02
Reply

Marsh Posté le 05-11-2009 à 13:18:14    

gcc à l'air de pas tenir compte des const& sur les types atomiques.

Reply

Marsh Posté le 05-11-2009 à 15:24:53    

Joel F a écrit :

gcc à l'air de pas tenir compte des const& sur les types atomiques.


 
Il donne pourtant le resultat que j'attends pour

Code :
  1. #include <iostream>
  2. #include <ostream>
  3. int i = 0;
  4. void f(int const& p)
  5. {
  6.     std::cout << "p = " << p << '\n';
  7.     i = 42;
  8.     std::cout << "p = " << p << '\n';
  9. }
  10. int main()
  11. {
  12.     f(i);
  13.     return 0;
  14. }



---------------
The truth is rarely pure and never simple (Oscar Wilde)
Reply

Marsh Posté le 05-11-2009 à 16:09:29    

il voulait dire const int & nope ?
oupa ?
ha non café :D


Message édité par bjone le 05-11-2009 à 17:15:10
Reply

Marsh Posté le 05-11-2009 à 17:45:38    

Un Programmeur a écrit :


Il donne pourtant le resultat que j'attends pour


 
je veut dire que le code généré pour f(int) et f(int cosnt& ) est identique ...

Reply

Marsh Posté le 05-11-2009 à 19:28:14    

C'est bien ce que j'avais compris.  Je vois mal comment c'est possible si on veut traiter correctement le genre de cas que j'ai donné (hormis si f est statique et qu'on ne passe jamais de pointeurs à f à une fonction dont on ne voit pas le code et tous les appels...).


---------------
The truth is rarely pure and never simple (Oscar Wilde)
Reply

Marsh Posté le 05-11-2009 à 19:43:16    

Un Programmeur a écrit :

C'est bien ce que j'avais compris.  Je vois mal comment c'est possible si on veut traiter correctement le genre de cas que j'ai donné (hormis si f est statique et qu'on ne passe jamais de pointeurs à f à une fonction dont on ne voit pas le code et tous les appels...).


 
Hmmmm, soit y a inference de l'origine de la référence soit ca a changé.
Je comprends pas pourquoi j'ai le résultat p=0,p=42 d'ailleurs au vu du code.

Reply

Marsh Posté le 05-11-2009 à 19:43:16   

Reply

Marsh Posté le 05-11-2009 à 19:50:49    

C'est pourtant le comportement attendu.  Une référence est un alias pour l'objet initial (ici i), le fait qu'on ne puisse pas modifier l'objet en utilisant cet alias n'empêche pas de pouvoir le faire en utilisant un autre accès.
 
Et si tu parles du code généré, ça me semble compréhensible ici -- g++ 4.2 sur x86.  En gros c'est compilé comme

Code :
  1. #include <iostream>
  2. #include <ostream>
  3. int i = 0;
  4. void f(int const* p)
  5. {
  6.     std::cout << "p = " << *p << '\n';
  7.     i = 42;
  8.     std::cout << "p = " << *p << '\n';
  9. }
  10. int main()
  11. {
  12.     f(&i);
  13.     return 0;
  14. }


---------------
The truth is rarely pure and never simple (Oscar Wilde)
Reply

Marsh Posté le 05-11-2009 à 19:59:25    

Code asm il voulait dire je pense :??:

Reply

Marsh Posté le 05-11-2009 à 20:12:43    

Et bien?

 

Appel de f dans main:

Code :
  1. .LCFI17:
  2. sub %esp, 4
  3. .LCFI18:
  4. mov DWORD PTR [%esp], OFFSET FLAT:i
  5. call f(int const& )
  6. add %esp, 4


on passe l'adresse de i.  Code de f

Code :
  1. .text
  2. .align 2
  3. .p2align 4,,15
  4. .globl f(int const& )
  5. .type f(int const& ), @function
  6. f(int const& ):
  7. .LFB1428:
  8. push %ebp
  9. .LCFI7:
  10. mov %ebp, %esp
  11. .LCFI8:
  12. sub %esp, 40
  13. .LCFI9:
  14. mov DWORD PTR [%ebp-4], %edi
  15. .LCFI10:
  16. mov %edi, DWORD PTR [%ebp+8]
  17. mov DWORD PTR [%ebp-8], %esi
  18. .LCFI11:
  19. lea %esi, [%ebp-13]
  20. mov DWORD PTR [%ebp-12], %ebx
  21. .LCFI12:
  22. mov %ebx, DWORD PTR [%edi]
  23. mov DWORD PTR [%esp+8], 4
  24. mov DWORD PTR [%esp+4], OFFSET FLAT:.LC0
  25. mov DWORD PTR [%esp], OFFSET FLAT:std::cout
  26. call std::basic_ostream<char, std::char_traits<char> >& std::__ostream_insert<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*, int)
  27. mov DWORD PTR [%esp+4], %ebx
  28. mov DWORD PTR [%esp], OFFSET FLAT:std::cout
  29. call std::basic_ostream<char, std::char_traits<char> >::operator<<(int)
  30. mov DWORD PTR [%esp+4], %esi
  31. mov BYTE PTR [%ebp-13], 10
  32. mov DWORD PTR [%esp+8], 1
  33. mov DWORD PTR [%esp], %eax
  34. call std::basic_ostream<char, std::char_traits<char> >& std::__ostream_insert<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*, int)
  35. mov DWORD PTR i, 42
  36. mov %ebx, DWORD PTR [%edi]
  37. mov DWORD PTR [%esp+8], 4
  38. mov DWORD PTR [%esp+4], OFFSET FLAT:.LC0
  39. mov DWORD PTR [%esp], OFFSET FLAT:std::cout
  40. call std::basic_ostream<char, std::char_traits<char> >& std::__ostream_insert<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*, int)
  41. mov DWORD PTR [%esp+4], %ebx
  42. mov DWORD PTR [%esp], OFFSET FLAT:std::cout
  43. call std::basic_ostream<char, std::char_traits<char> >::operator<<(int)
  44. mov DWORD PTR [%esp+4], %esi
  45. mov BYTE PTR [%ebp-13], 10
  46. mov DWORD PTR [%esp+8], 1
  47. mov DWORD PTR [%esp], %eax
  48. call std::basic_ostream<char, std::char_traits<char> >& std::__ostream_insert<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*, int)
  49. mov %ebx, DWORD PTR [%ebp-12]
  50. mov %esi, DWORD PTR [%ebp-8]
  51. mov %edi, DWORD PTR [%ebp-4]
  52. mov %esp, %ebp
  53. pop %ebp
  54. ret


On voit bien qu'on déréférence ce qui est passé (DWORD PTR[%edi]).

 

(g++ -O2 -masm=intel -S puis le résultat est passé dans c++filt pour démangler les noms)


Message édité par Un Programmeur le 05-11-2009 à 20:15:04

---------------
The truth is rarely pure and never simple (Oscar Wilde)
Reply

Marsh Posté le 05-11-2009 à 20:22:38    

je viens de vérifier. Je m'a fait eu comme une tanche donc.

Reply

Marsh Posté le 05-11-2009 à 21:06:21    

bon in finé c'est quoi le verdict en terme de perf :$


---------------
.
Reply

Marsh Posté le 05-11-2009 à 21:22:14    

J'ai du mal à comprendre pourquoi tu veux comparer par valeur et par référence non constante, le choix entre les deux doit se faire à mon avis sur des considérations sémantiques.
 
Entre par valeur et par référence constante et si on a le choix -- autrement dit, si les considérations de possibilité d'alias n'impose pas l'un ou l'autre -- par valeur devrait généralement être plus performant (mais comme toujours 1/ est-ce que ce n'est pas prématuré d'envisager ce genre de chose 2/ mesure 3/ est-ce que le gain vaut la peine)


---------------
The truth is rarely pure and never simple (Oscar Wilde)
Reply

Marsh Posté le 05-11-2009 à 21:23:44    

et surtout paye ta micro-optimisation qui sert à rien 99% du temps

Reply

Marsh Posté le 05-11-2009 à 21:32:58    

pour mesurer sous visual, vous utilisez quoi  typiquement ? je me heurte à ce problème , QueryCouter & co ? et si oui de quelle manière le faite vous


---------------
.
Reply

Marsh Posté le 05-11-2009 à 22:17:27    

no idea ?


---------------
.
Reply

Marsh Posté le 05-11-2009 à 22:40:59    

Tu veux mesurer quoi ? Une différence entre passage par référence et passage par valeur ?

Reply

Marsh Posté le 05-11-2009 à 22:44:29    

exact


---------------
.
Reply

Marsh Posté le 06-11-2009 à 00:57:05    

Tu va mesurer du bruit :D
 
Quand c'est une implémentation d'un algo avec une charge de travail réaliste, les queryperfcounters & autres sont corrects.
 
Mais pour ce genre de trucs faudrait du rdtsc.
 
Dans tous les cas c'est de l'enculage de mouche, d'autant plus que la donne peut changer si le compilo peut faire de l'inlining sauvage ou de la compilation lors de l'édition des liens, ou pas (link dll/lib statique).
 
Comme dit plus haut, le code tu le fais de la manière la plus élégante possible et la plus cohérente avec l'intention initiale, et autrement pour un type qui tiens dans un ou deux registre => valeur, classe/struct => ref.


Message édité par bjone le 09-11-2009 à 16:55:21
Reply

Marsh Posté le 07-11-2009 à 14:59:01    

ok ok donc au final ça revient au même alors


---------------
.
Reply

Marsh Posté le 08-11-2009 à 10:24:39    

A lire avant de chercher a optimiser http://www.linux-kongress.org/2009 [...] eitner.pdf


---------------
The truth is rarely pure and never simple (Oscar Wilde)
Reply

Marsh Posté le 08-11-2009 à 10:35:40    

/me bookmark this

Reply

Marsh Posté le 08-11-2009 à 17:13:58    

thanks pour le lien


---------------
.
Reply

Marsh Posté le    

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed