ohayoo minna, j'aimerai bien savoir le rôle de la fonction Inline, j'ai jeté un coup d'oeil sur un cour de " Christian Casteyde " sur C++ mais je craint que j'ai pas bien compris 8O:cry: , donc je vous pris de m'aider. merci d'avance ;)
Version imprimable
ohayoo minna, j'aimerai bien savoir le rôle de la fonction Inline, j'ai jeté un coup d'oeil sur un cour de " Christian Casteyde " sur C++ mais je craint que j'ai pas bien compris 8O:cry: , donc je vous pris de m'aider. merci d'avance ;)
Bonjour,
En gros c'est une macro en plus sécurisée : Les fonctions en ligne.
Salut,
Pour simplifier, on pourrait dire que, quand tu appelle une fonction dans un programme, les instructions créées pour le compilateur font qu'une série d'informations est mise (de tete, la valeur du pointeur courent, et les valeurs des différents différents accus...Mais peut etre encore d'autres?) en "stack" (pille) au sein du processeur.
La pille, c'est un peu de mémoire qui est destiné à permettre au processeur de reprendre l'exécution d'un programme là ou il l'avait laissé avant d'entrer dans une sous routine.
L'astuce c'est que la sauvegarde et la récupération de ces informations, ca prend du temps, et qu'en plus, la pille n'est pas infini (les erreur "stack overflow" arrivent quand on essaye de mettre des valeurs en pille, mais que la capacité maximale de celle-ci est atteinte)
L'idée d'une fonction inline, c'est de dire que "je sais que j'ai créé une fonction, mais je voudrais que les instructions qu'elle contient soient intégrée directement dans ma routine, plutot que de faire jouer le phénomene d'appel des routines du processeur"
L'exemple classique que l'on pourrait donner est celui d'un accesseur dans une classe:
Faire jouer l'appel d'une routine pour quelque chose qui, en définitive, ne demande qu'à récupérer la valeur d'un entier, c'est un peu lourd...Code:
1
2
3
4
5
6
7
8
9
10 class maclasse { private: //un membre prive int monnombre; public: //l'accesseur pour le membre int GetMonNombre(); }
C'est la raison pour laquelle, on préférera souvent déclarer la fonction inline, ce qui indiquera au préprocesseur que "partout ou tu tombera sur GetMonNombre(), ben, tu le remplacera par les instruction que la fonction comporte"
Mais c'est une lame à double tranchant: Tu gagne en rapidité d'exécution et en économie de la pille ce que tu perd en taille de l'exécutable fini (si tu as une fonction inline plus importante que celle prise dans mon exemple, et que tu l'appelle 100 fois, ses instructions seront recopiée 100 fois dans l'exécutable, alors que, s'il s'était agit d'une fonction normale, on ne les aurait eu qu'une seule fois dans l'exécutable fini)
Bonjour,
C'est même bien pire que cela : comme il est à la discrétion du compilateur d'effectivement mettre, ou non, la fonction inline, il peut parfaitement la mettre inline dans une partie du code, et comme une fonction ordinaire dans une autre partie (c'est parfaitement légal pour la norme).Citation:
Envoyé par koala01
Il y a des cas où ce comportement "indéfini" posera problème.
Donc, bien savoir ce que l'on fait avec la directive inline.
Citation:
Envoyé par thewho
Ne t'arrête pas en si bon chemin, tu m'intéresses là ! Il existe des cas où le comportement du code peut être changé par le fiat d'inliner ou non une fonction ?? 8O
Tu pourrais développer par un exemple ?
Apres quelques recherche j'en suis arrivé a la conclusion qu'il fallait laisser le navigateur inliner comme bon lui semblait, dans 90% des cas c'est préférable .
merci les amis ( surtout KOALA 01), grâce à vous j'ai compris un peu l'interet de cette fonction :P mais si vous permettez :oops: ( ça sera trés gentil ) de me donner encore plus d'information par ce que c'est pas encore 100% visible ( vù que j'ai quelques ptites difficultées dans la langues française) merci encore ;)
A titre personnel, je n'inline moi-même que les accesseurs sur les membres privés et autres fonctions qui ne font vraiment qu'une ou deux instructions...Citation:
Envoyé par Clad3
Quoi qu'il en soit, je n'inline jamais une fonction qui contient un (ou plusieurs) boucles, et je laisse le soin au compilo de décider pour les autres comment il les gère ;)
Gege2061 à posté le lien de la FAQ c'est assez explicite.Citation:
Envoyé par gege2061
C'est pour informer le compilateur que tu aimerais qu'il puisse mettre en ligne la fonction, c'est une optimisation, mais le compilateur, peut ou non prendre en compte l'information. Tu peux inliner une fonction A, et ne pas inliner une fonction B, mais le compilateur peut très bien ne pas inliner la fonction A et inliner la fonction B.
C'est de moins en moins utilisé, car les machines sont puissantes, marquer inline partout est inutile, le compilateur sera surement mieux le faire que toi.
A moins que tu souhaites pour X raison demander d'inliner une fonction spécifique, en pensant que peut être cela pourrait aller plus vite.
ps: Cela ne change en rien ton code, juste les performances.
Merci Merci beaucoups , maintenant je serai sûr de ce que je ferai (inchallah) graçe à vous bien evidement, merci encore et a+:mrgreen:
Bonjour,
Je n'ai pas d'exemple en tête, mais le bouquinCitation:
Envoyé par vinny_the_true
Scott Meyers - "Effective C++"
le montre bien, avec certes des exemples plus ou moins tordus, et montre quelques dangers/problèmes dus au fait de laisser le compilateur décider s'il met inline ou non.
Un des problèmes dont je me souviens assez bien est:
- Les fonctions "inline" sont normalement définies dans un fichier .h.
- Si le compilateur décide de ne pas la mettre "inline", il lui faut éviter le problème de "multi-définition" lors du link (car alors la fonction serait définie dans chaque module incluant le .h en question), pour cela, il déclare automatiquement la fonction static dans ce fichier.
- On a alors a une définition locale de la fonction pour chaque fichier ayant inclu le .h
- On perd donc le principal avantage du "inline" : on fait des appels de fonction ordinaires
- ET on perd l'avantage de garder une fonction ordinaire, qui est le gain de place : la fonction existe alors en plusieurs exemplaires (qui peuvent être relativement nombreux pour les gros projets).
Tiens justement, ya pas un moyen de savoir si le compilateur nous a refusé un inline ? J'ai jamais trouvé dans Visual C++ ni GCC...Citation:
Envoyé par thewho
Sous Visual, tu peux activer un warning pour cela.
Cherche à "warnings that are off by default"...
-Winline pour GCC, pas si difficile que ça a trouver...Citation:
Tiens justement, ya pas un moyen de savoir si le compilateur nous a refusé un inline ? J'ai jamais trouvé dans Visual C++ ni GCC...
Par contre si quelqu'un connaissait le moyen de forcer les inlines, en particulier sur GCC, je suis vraiment vraiment intéressé.
Il y a bien '__forceinline' sous VC, mais je l'impression que ça marche pas à tous les coups. C'est quand-même déjà ça.
'inline' est au mieux une indication, qui plus est généralement redondante; ces extensions sont beaucoup plus utiles surtout dans le contexte de l'optimisation globale - par exemple au moment du linkage.
ICC les supporte aussi, dans une des 2 formes selon le compilo qu'il émule.Code:
1
2
3
4
5
6
7 // MSVC #define FINLINE __forceinline #define NOINLINE __declspec(noinline) // GCC #define FINLINE __attribute__((always_inline)) #define NOINLINE __attribute__((noinline))
Note: échouer n'est pas une option :)
J'avais essayé, mais ça ne marche absolument pas. Cette option est une arnaque...Citation:
Code:
1
2#define FINLINE __attribute__((always_inline))
J'avais essayé avec ICC sous Linux, ça marchait pas non plus (ni __forceinline, ni __attribute)Citation:
ICC les supporte aussi, dans une des 2 formes selon le compilo qu'il émule.
J'utilise principalement ICL (ICC sous windows), __forceinline marche en général pas trop mal, mais j'ai vu des différences notables d'une version à l'autre. Je me suis callé sur une version un peu ancienne de ICL, mais qui marche nickel.
Sous Visual, il me semble que le warning indique généralement pourquoi une fonction n'a pas pu être inlinée...
Je regrette, mais cela fonctionne de façon fiable depuis des lustres; encore faut-il noter que cela doit faire partie de la déclaration de la fonction.Citation:
Envoyé par Charlemagne
Encore une fois je regrette, mais que celà soit avec la version 8 ou 9 d'ICC, sous Linux ou windows, avec force/noinline, j'ai tjs obtenu un résultat déterministe.Citation:
Envoyé par Charlemagne
Mais la aussi, cela doit apparaitre dans la déclaration.
Sur mon projet en tout cas ça ne marche pas. Mais peut-être bien que les fonctions que je désire inliner sont trop nombreuses ou trop volumineuses au goût de GCC et de ICC. L'option 'Winline' de GCC me confirmait bien qu'il n'en faisait qu'à sa tête en refusant obstinément d'inliner tout un tas de fonctions.Citation:
Encore une fois je regrette, mais que celà soit avec la version 8 ou 9 d'ICC, sous Linux ou windows, avec force/noinline, j'ai tjs obtenu un résultat déterministe.
Mais la aussi, cela doit apparaitre dans la déclaration.
La vitesse d'exécution s'en trouve sérieusement ralentie par rapport à ICL sur des fonctions critiques (environ 2x plus lent).
Ca me surprend de la part d'ICC, parce que ICL réagit bien aux inlines forcés, pourtant je croyais que ICC était sous Linux le pendant d'ICL.
'inline' est une indication facultative, l'attribut 'always_inline' est imperatif; en cas d'impossibilité, gcc lève une erreur.Citation:
Envoyé par Charlemagne
Si ce n'est pas le cas, c'est par définition un bug.
Le dernier que j'ai rapporté sur le sujet étant http://gcc.gnu.org/bugzilla/show_bug.cgi?id=26667 mais c'était une subtilité.
Si vous avez de quoi substancier vos propos, il serait de bon ton de soumettre un rapport de bug.
ICC peut pratiquer une optimisation globale au link-time, ce que gcc ne peut faire pour l'instant; cela a une incidence particuliere sur l'inlining, les statiques et les conventions d'appel etc... Qui plus est ICC est par défaut beaucoup plus aggressif.Citation:
Envoyé par Charlemagne
Il y a des moyen de contourner cette limitation, notament avec -combine (pour l'instant incompatible avec le C++), la réduction de la visibilité par défaut et autre siouxerie, mais cela reste délicat.
En géneral j'obtiens plus facilement du code de qualité de GCC que d'ICC... pour ce que ça vaut :)
Après plusieurs correspondances, je m'étais résolu à poster un rapport de bug (y'a environ 16 mois de cela), resté sans réponse...Citation:
Si vous avez de quoi substancier vos propos, il serait de bon ton de soumettre un rapport de bug.
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=21628
J'ai jamais réussi à obtenir de GCC ni de ICC, ni de VC, une vitesse aprochant ICL. Maintenant je préfererais me tromper, car si quelqu'un pouvais me prouver le contraire, ça m'arrangerait.
Un exemple (sur une FFT) est décrit dans le rapport de bug.
Et vous n'obtiendrez jamais aucune réponse à moins que de fournir un source pré-processé, c.a.d. compilable par lui même.Citation:
Envoyé par Charlemagne
Les dev. de gcc peuvent être pénibles, mais si il y a une chose qu'ils ne peuvent refuser c'est un os à ronger ;)
La série 4.x donne de bien meilleur résultat en C++ et pour ce qui du 'floating point intensive'; c'est flagrant lors de l'usage de SSE, en génération automatique - scalaires - ou vectoriel - via intrinsics.Citation:
Envoyé par Charlemagne
J'ai un raytracer cohérent temps-réel, avec notament un chemin tout en SSE vectorisé. Que celà soit pour la construction du kd-tree (SAH) ou le rendu, en vectoriel ou scalaire, le binaire produit par gcc 4.2 est au moins aussi rapide que celui produit par ICC 9.1. En 32bit comme en 64bit. Msvc8 est à la ramasse d'au moins 25%.
Comme je l'ai dis précedement celà demande une certaine, disons, attention.
D'un autre coté il est beaucoup plus facile d'éduquer gcc que les 2 autres compilateurs.
PS: icc & icl à version égale produisent la meme chose, modulo le fait que dans un cas msvc est émulé (bug inclus) et gcc dans l'autre et que les bibliotheques attenantes different du fait de l'environement. J'insiste sur ce dernier point.
Tant pis. GCC restera lent.Citation:
Et vous n'obtiendrez jamais aucune réponse à moins que de fournir un source pré-processé, c.a.d. compilable par lui même.
Encore jamais essayé de version 4.Citation:
La série 4.x donne de bien meilleur résultat en C++ et pour ce qui du 'floating point intensive'; c'est flagrant lors de l'usage de SSE, en génération automatique - scalaires - ou vectoriel - via intrinsics.
Elle n'existait pas quand j'ai posté mon rapport. Et puis les rares fois que j'utilise GCC, c'est plutôt sous Cygwin car je ne connais pas bien Linux et je n'ai pas facilement accès à des machines sous Linux. La version 4 ne semble malheureusement pas disponible sous Cygwin...
Je ne crois pas à la génération automatique d'instructions SSE (certes j'ai jamais essayé), ça ne vaudra jamais les intrinsiques.
Tu peux s'il te plaît essayer de compiler mon petit exemple sous GCC 4.X pour que je puisse comparer avec ICL.
PS:
J'ai été fortement décu par ICL 9. Je sais pas ce qu'Intel a changé, mais ça vaut pour moi franchement pas la version 8.1. Je teste pourtant de tant en tant les nouvelles versions.Citation:
le binaire produit par gcc 4.2 est au moins aussi rapide que celui produit par ICC 9.1. En 32bit comme en 64bit. Msvc8 est à la ramasse d'au moins 25%.
Si, si. Elle existait. http://gcc.gnu.org/releases.htmlCitation:
Envoyé par Charlemagne
La version fournie en standard par Cygwin est tjs une 3.4.x je crois. La 4.2.0 ne devrait plus tarder, et de toute façon il suffit d'attraper un snapshot, ftp://gcc.gnu.org/pub/gcc/snapshots/ , et de le recompiler, Cygwin étant une cible majeure et supportée.
L'auto-vectorisation vaut ce qu'elle vaut, c'est à dire pas grand chose tant pour gcc qu'icc. Mais comme je l'ai dit, que celà soit avec du C++ pur sucre + géneration de SSE scalaire ou via les intrinsics, gcc produit du code au moins aussi bon qu'icc si ce n'est meilleur.Citation:
Envoyé par Charlemagne
Bon, l'exemple date un peu, mais 5M rayons/s sur un cpu j'aurais tendance a dire que c'est honnête: http://ompf.org/ray/wip/pix/20060201-01.jpg
Donc...
Chacun voit midi à sa porte. Mais il est tjs dangereux de se lancer dans des generalisations :)Citation:
Envoyé par Charlemagne
Ton test-case est incomplet.Citation:
Envoyé par Charlemagne
EDIT pour répondre à l'edit: v8.1, v9.1, 32bit, 64bit même combat de nos jours (meme si 2 ans en arriere gcc se faisait pulveriser en 32bit par icc 8.1... ce n'est plus le cas)
J'attendrai donc la version 4.X sous Cygwin pour comparer avec ICL. Ca fait néanmoins plus d'un an que je l'attends, sans trop d'impatience toutefois.
J'ai pas trop envie de compiler moi-même GCC, j'ai jamais fais ça, et c'est surement compliqué quand on connait pas.
C'est surtout que ça contribue au réchauffement global. Sinon, il y a tjs ce mémo: http://ompf.org/forum/viewtopic.php?t=29Citation:
Envoyé par Charlemagne