Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

fonctions inline, théorie et pratique

11 réponses
Avatar
Korchkidu
Bonjour =E0 tous,

les fonctions inline sont en th=E9orie faites pour rendre le code plus
rapide. Pourtant, il me semble me souvenir d'une discussion qui
soutenait que de toute fa=E7on, =E7a ne servait =E0 rien car le compilateur
faisait ce qu'il voulait au final. Est-ce vrai ? Dans ce cas, =E0 quoi
=E7a sert de "inliner" des fonctions (=E0 part faire une siggestion au
compilateur) ? Est-ce qu'en inlinant correctement ses fonctions on
arrive =E0 des gains de performances en pratique ?

Meilleures salutations.
K.

10 réponses

1 2
Avatar
Michael Doubez
On 28 juil, 08:42, Korchkidu wrote:
les fonctions inline sont en théorie faites pour rendre le code plus
rapide. Pourtant, il me semble me souvenir d'une discussion qui
soutenait que de toute façon, ça ne servait à rien car le compilate ur
faisait ce qu'il voulait au final. Est-ce vrai ? Dans ce cas, à quoi
ça sert de "inliner" des fonctions (à part faire une siggestion au
compilateur) ? Est-ce qu'en inlinant correctement ses fonctions on
arrive à des gains de performances en pratique ?



Voir FAQ Lite
http://www.parashift.com/c++-faq-lite/inline-functions.html
En français (vieille version):
http://jlecomte.ifrance.com/c++/c++-faq-lite/inline-functions-fr.html

--
Michael
Avatar
Korchkidu
On Jul 28, 9:19 am, Michael Doubez wrote:
On 28 juil, 08:42, Korchkidu wrote:

> les fonctions inline sont en théorie faites pour rendre le code plus
> rapide. Pourtant, il me semble me souvenir d'une discussion qui
> soutenait que de toute façon, ça ne servait à rien car le compila teur
> faisait ce qu'il voulait au final. Est-ce vrai ? Dans ce cas, à quoi
> ça sert de "inliner" des fonctions (à part faire une siggestion au
> compilateur) ? Est-ce qu'en inlinant correctement ses fonctions on
> arrive à des gains de performances en pratique ?

Voir FAQ Litehttp://www.parashift.com/c++-faq-lite/inline-functions.html
En français (vieille version):http://jlecomte.ifrance.com/c++/c++-faq-l ite/inline-functions-fr.html



Merci pour ta réponse... ça, c'est ce que j'appelle la théorie. Mais
en pratique ?

K.
Avatar
James Kanze
On Jul 28, 8:42 am, Korchkidu wrote:

les fonctions inline sont en théorie faites pour rendre le
code plus rapide. Pourtant, il me semble me souvenir d'une
discussion qui soutenait que de toute façon, ça ne servait à
rien car le compilateur faisait ce qu'il voulait au final.
Est-ce vrai ? Dans ce cas, à quoi ça sert de "inliner" des
fonctions (à part faire une siggestion au compilateur) ?
Est-ce qu'en inlinant correctement ses fonctions on arrive à
des gains de performances en pratique ?



La motivation derrière les fonctions inline, c'est de pouvoir
donner au compilateur d'avantage d'informations, de lui dire que
cette fonction risque d'être appelée souvent, dans des boucles
critiques, et que ça pourrait être utile à l'optimisation de la
générer en ligne. C'est l'*intention* des auteurs du C++ que le
compilateur le génère en ligne s'il peut, et s'il n'est pas
capable de faire mieux que le programmeur. Dans ce sens, il est
comme register, à la difference près qu'aujourd'hui, prèsque
tous les compilateurs peuvent réelement faire mieux que le
programmeur en ce qui concerne register, tandis qu'il n'y a que
fort peu qui y arrive en ce qui concerne inline.

De point de vue formelle, évidemment, ce n'est qu'une
recommendation au compilateur. Pour diverses raisons techniques,
on ne peut jamais lui imposer la génération en ligne, et la
norme (même C) a toujours permis au compilateur tout ce qui ne
modifie le comportement visible du programme, y compris la
génération en ligne des fonctions, déclarées inline ou non.
Formellement, tout ce que inline fait, c'est de permettre (et
exiger) la définition de la fonction dans toutes les unités de
traduction qui l'utilisent. Mais il n'y a pas que le formel :
formellement, il n'y a rien non plus qui interdit au compilateur
de générer une boucle vide de cinq minutes d'attente à chaque
point-virgule. Dans la pratique, il y a quelque chose qui
s'appelle la qualité de l'implémentation, et la qualité de
l'implémentation prend bien en compte l'intention, et non
seulement la lettre de la norme. Certains compilateurs (très
peu) font assez d'analyse pour mieux savoir que le programmeur
ce qui doit être inline ; ils traitent l'inline exactement comme
n'importe quelle autre fonction. Et certaines fonctions posent
des problèmes à la génération en ligne (des fonctions
récursives, par exemple) -- elles ne seront pas générées en
ligne, quoique tu fasses. Pour la reste, c'est une question de
la qualité de l'implémentation.

--
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
Avatar
Mathias Gaunard
On 28 juil, 08:42, Korchkidu wrote:
Dans ce cas, à quoi
ça sert de "inliner" des fonctions (à part faire une siggestion au
compilateur) ?



À avoir un linkage faible, ce qui permet d'avoir la définition de la
fonction dans plusieurs unités de traduction.
Sinon, ce serait une erreur.

Note que les fonctions membres définies dans la définition d'une
classe sont également inline de manière implicite, sinon cela
causerait des erreurs à l'édition de liens.
Avatar
pjb
James Kanze writes:

[...] Certains compilateurs (très
peu) font assez d'analyse pour mieux savoir que le programmeur
ce qui doit être inline ; ils traitent l'inline exactement comme
n'importe quelle autre fonction. Et certaines fonctions posent
des problèmes à la génération en ligne (des fonctions
récursives, par exemple) -- elles ne seront pas générées en
ligne, quoique tu fasses. Pour la reste, c'est une question de
la qualité de l'implémentation.



Si c'est une recursion terminale, et que le compilateur sait
l'optimiser, alors il peut facilement mettre la fonction en ligne,
puisqu'elle n'est plus qu'un boucle.

--
__Pascal Bourguignon__
Avatar
Falk Tannhäuser
Pascal J. Bourguignon schrieb:
James Kanze writes:
[...] Certains compilateurs (très
peu) font assez d'analyse pour mieux savoir que le programmeur
ce qui doit être inline ; ils traitent l'inline exactement comme
n'importe quelle autre fonction. Et certaines fonctions posent
des problèmes à la génération en ligne (des fonctions
récursives, par exemple) -- elles ne seront pas générées en
ligne, quoique tu fasses. Pour la reste, c'est une question de
la qualité de l'implémentation.



Si c'est une récursion terminale, et que le compilateur sait
l'optimiser, alors il peut facilement mettre la fonction en ligne,
puisqu'elle n'est plus qu'une boucle.



GCC 4.3.2 le fait à partir du niveau d'optimisation -O2, tandis que GCC 3.4.4 ne le faisait pas - on n'arrête pas la progrès !
Je suis sous Cygwin et j'ai essayé avec la fonction

unsigned factorial(unsigned n)
{
return n <= 1 ? 1 : n * factorial(n - 1);
}

Falk
Avatar
Gabriel Dos Reis
Falk Tannhäuser writes:

| Pascal J. Bourguignon schrieb:
| > James Kanze writes:
| >> [...] Certains compilateurs (très
| >> peu) font assez d'analyse pour mieux savoir que le programmeur
| >> ce qui doit être inline ; ils traitent l'inline exactement comme
| >> n'importe quelle autre fonction. Et certaines fonctions posent
| >> des problèmes à la génération en ligne (des foncti ons
| >> récursives, par exemple) -- elles ne seront pas génér ées en
| >> ligne, quoique tu fasses. Pour la reste, c'est une question de
| >> la qualité de l'implémentation.
| >
| > Si c'est une récursion terminale, et que le compilateur sait
| > l'optimiser, alors il peut facilement mettre la fonction en ligne,
| > puisqu'elle n'est plus qu'une boucle.
|
| GCC 4.3.2 le fait à partir du niveau d'optimisation -O2, tandis que
| GCC 3.4.4 ne le faisait pas - on n'arrête pas la progrès !

GCC optimisait la recursivité terminale depuis bien longtemps (du moin s,
quand j'étais encore étudiant).

| Je suis sous Cygwin et j'ai essayé avec la fonction
|
| unsigned factorial(unsigned n)
| {
| return n <= 1 ? 1 : n * factorial(n - 1);
| }

Ceci n'est pas une recursivité terminale.

-- Gaby
Avatar
James Kanze
On Jul 30, 2:57 am, Gabriel Dos Reis wrote:
Falk Tannhäuser writes:



> Pascal J. Bourguignon schrieb:
> > James Kanze writes:
> >> [...] Certains compilateurs (très
> >> peu) font assez d'analyse pour mieux savoir que le programmeur
> >> ce qui doit être inline ; ils traitent l'inline exactement comme
> >> n'importe quelle autre fonction. Et certaines fonctions posent
> >> des problèmes à la génération en ligne (des fonctions
> >> récursives, par exemple) -- elles ne seront pas générées en
> >> ligne, quoique tu fasses. Pour la reste, c'est une question de
> >> la qualité de l'implémentation.



> > Si c'est une récursion terminale, et que le compilateur sait
> > l'optimiser, alors il peut facilement mettre la fonction en ligne,
> > puisqu'elle n'est plus qu'une boucle.



> GCC 4.3.2 le fait à partir du niveau d'optimisation -O2, tandis que
> GCC 3.4.4 ne le faisait pas - on n'arrête pas la progrès !



GCC optimisait la recursivité terminale depuis bien longtemps
(du moins, quand j'étais encore étudiant).



> Je suis sous Cygwin et j'ai essayé avec la fonction



> unsigned factorial(unsigned n)
> {
> return n <= 1 ? 1 : n * factorial(n - 1);
> }



Ceci n'est pas une recursivité terminale.



Je ne me rappelle plus des détails, mais il me semble que si la
profondeur est finie, et connue au point de l'appel, g++ génère
en ligne aussi, en duplicant le code, jusqu'à certain niveau.

--
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
Avatar
Jean-Marc Bourguet
Olivier Miakinen <om+ writes:

Le 30/07/2009 02:57, Gabriel Dos Reis a écrit :

GCC optimisait la recursivité terminale depuis bien longtemps (du moins,
quand j'étais encore étudiant).

| Je suis sous Cygwin et j'ai essayé avec la fonction
|
| unsigned factorial(unsigned n)
| {
| return n <= 1 ? 1 : n * factorial(n - 1);
| }

Ceci n'est pas une recursivité terminale.



Si je ne me trompe pas, la version avec récursivité terminale serait :

unsigned factorial(unsigned n, unsigned res = 1)
{
return n <= 1 ? res : factorial(n - 1, n * res);
}



Pas tout à fait (le calcul est fait dans l'autre sens, vu l'associativité
de la multiplication ça ne change pas le résultat ici).

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
Avatar
Olivier Miakinen
Le 30/07/2009 02:57, Gabriel Dos Reis a écrit :

GCC optimisait la recursivité terminale depuis bien longtemps (du moins,
quand j'étais encore étudiant).

| Je suis sous Cygwin et j'ai essayé avec la fonction
|
| unsigned factorial(unsigned n)
| {
| return n <= 1 ? 1 : n * factorial(n - 1);
| }

Ceci n'est pas une recursivité terminale.



Si je ne me trompe pas, la version avec récursivité terminale serait :

unsigned factorial(unsigned n, unsigned res = 1)
{
return n <= 1 ? res : factorial(n - 1, n * res);
}
1 2