# [Gcc] Optimisation de compilation avec ~amd64 kde gcc4.1.1

## apocryphe

Bsr,

Je vais bientot re-installer ma gentoo

j'aimerai ajouter un peu de piment lors de la compilation

j'utilise gcc 4.1.1 kde sur ~amd64

J'ai un cpu mobile hammer amd64 3200+

je compte utiliser pour mon make.conf:

 *Quote:*   

> 
> 
> CFLAGS="-march=k8 -pipe -O2 -mmmx -msse -msse2 -m3dnow -fgcse-after-reload -floop-optimize2 -ftracer -ftree-vectorize"
> 
> CHOST="x86_64-pc-linux-gnu"
> ...

 

Pouvez vous emettre des avis, vos experience, l'ajout ou la supression des options

merci

----------

## Oni92

Les options -mmmx -msse -msse2 -m3dnow  sont inutiles dans ton cflags car déjà inclue avec l'option -march=k8.

----------

## apocryphe

 *Oni92 wrote:*   

> Les options -mmmx -msse -msse2 -m3dnow  sont inutiles dans ton cflags car déjà inclue avec l'option -march=k8.

 

certain ebuild inibe le march, cela permet de "forcer" l'optimisation

----------

## apocryphe

Bon aprés qvoir glanner des info a droite a gauche je suis arrivé a ce make.conf

 *Quote:*   

> 
> 
> CFLAGS="-march=k8 -pipe -O2 -mmx -msse -msse2 -m3dnow -fomit-frame-pointer -fgcse-after-reload -floop-optimize2 -ftracer -ftree-vectorize -floop-optimize2 -ftracer"
> 
> CHOST="x86_64-pc-linux-gnu"
> ...

 

vivement que je re-install...

----------

## guilc

 *apocryphe wrote:*   

>  *Oni92 wrote:*   Les options -mmmx -msse -msse2 -m3dnow  sont inutiles dans ton cflags car déjà inclue avec l'option -march=k8. 
> 
> certain ebuild inibe le march, cela permet de "forcer" l'optimisation

 

Certains ebuilds les inhibes oui, mais il y a une bonne raison. L'instabilité.

Par expérience, il n'est pas bon de mettre ces cflags là, il n'apportent que des problèmes (oui, moi aussi je mettais beaucoup de redondance, puis j'ai tout viré au fil des mésaventures que ça ammenait).

De même pour "-fvisibility-inlines-hidden -enable-gcc-hidden-visibility". déconseillé. Les ebuilds sur lesquels c'est bénéfique (genre les ebuilds de kde) le gèrent correctement, activable via un use flag.

Quant à ça :  "-ftracer -ftree-vectorize", amha ce n'est pas mature et pose encore des problème suivant les paquets...

bref, tu l'auras compris, pour moi (et pour beaucoup d'autres), les seuls cflags safe sont -march/-mtune et -O2 (et bien sur -pipe)  :Wink: 

----------

## guilc

Tiens, ton LDFLAGS aussi, c'est une horreur !

En tous cas, avec tout ça dans ton make.conf, ne t'avises pas de faire un bug report, tu va te faire jeter direct, c'est vraiment chercher la m**** pour des optimisations minimes... Et les devs n'acceptent jamais les bug reports faits avec des paquets compilés avec ça (l'hypothèse la plus gentille étant que tu te fasse flamer en te faisant traiter de sale "ricer"  :Laughing:  )

----------

## Scullder

 *guilc wrote:*   

> De même pour "-fvisibility-inlines-hidden -enable-gcc-hidden-visibility". déconseillé. Les ebuilds sur lesquels c'est bénéfique (genre les ebuilds de kde) le gèrent correctement, activable via un use flag.

 

L'expérience que j'ai de ces options, c'est que c'est une prise de tête pas possible, que ça peut générer des binaires cassés, et causer des problèmes indirectement en chaîne, genre la compilation qui plante à cause d'une dépendence qui a été compilée avec ces flags. Après ça devient mission impossible pour compiler certains paquets (trouver quel flag sur quel prog pose problème), et même quand on veut s'en débarasser, y'a encore des restes.

D'ailleurs, j'ai jamais réussi à compiler certains prog comme xmoto alors que ça n'a rien d'exceptionnel  :Crying or Very sad: 

 *guilc wrote:*   

> En tous cas, avec tout ça dans ton make.conf, ne t'avises pas de faire un bug report, tu va te faire jeter direct, c'est vraiment chercher la m**** pour des optimisations minimes... Et les devs n'acceptent jamais les bug reports faits avec des paquets compilés avec ça (l'hypothèse la plus gentille étant que tu te fasse flamer en te faisant traiter de sale "ricer"  )

 

En fait, le truc, c'est qu'à force, on se fait un répertoire /etc/portage/env qui va bien, et ça va tout seul, mais ça prend du temps.

Pour le bugzilla, j'ai déjà posté un emerge --info avec ce genre de flags pour une requête de keyword ~amd64, on ne m'a pas incendié xD, par contre si c'est pour reporter un problème de compilation, un segfault ou un problème de comportement, ça va pas le faire. On peut toujours recompiler sans ces flags, et demander confirmation à d'autres personnes.

J'ai des doutes sur les performances avec tous ces flags. En même temps, j'ai pas de problème de fiabilité non plus. A force de cumuler les flags, on finit par augmenter la taille du binaire, et pour d'autres commes les flags d'optimisations sur les boucles ou pour automatiquement inliner des fonctions selon leur taille, ça dépend d'un savant équilibre entre taille du binaire ou morceau de code binaire et taille du cache du cpu... Bref, pas évident à gérer.

Mon avis, c'est que si t'as un peu de temps en plus à consacrer à ta gentoo et que la stabilité de ton système n'est pas critique, garde ces flags xD

Vala une partie de mon make.conf de ricer  :Laughing:  si ça vous intéresse (à revoir d'ailleurs, certains trucs ne sont plus utiles)   

```
% cat /etc/make.conf

# These settings were set by the catalyst build script that automatically built this stage

# Please consult /etc/make.conf.example for a more detailed example

CFLAGS="-march=k8 -pipe -O3 -ftree-vectorize -DNDEBUG -ffast-math -ftracer -funroll-loops -freorder-blocks-and-partition"

CHOST="x86_64-pc-linux-gnu"

CXXFLAGS="${CFLAGS} -fno-enforce-eh-specs -enable-gcc-hidden-visibility -fvisibility-inlines-hidden -fvisibility=hidden"

LDFLAGS="-Wl,-O1 -Wl,--as-needed -Wl,--sort-common -s -Wl,--hash-style=both"

EXTRA_ECONF="--enable-new_ldflags"

MAKEOPTS="-j2"

USE="-gtk -gtk2 -gnome -java qt kde kdeenablefinal kdehiddenvisibility xcb gpm alsa -oss -arts -esd ssl nls nptl gcj unicode dbus dri xinerama truetype png svg gif jpeg -tiff pdf bzip2 mp3 mp4 ogg theora vorbis x264 aac a52 xvid quicktime asf matroska srt -mad -mikmod v4l v4l2 -cups opengl nvidia xcomposite gpm hal dbus dvd dvdread -dvdr cdr xine -gstreamer ffmpeg -ipv6 -ldap dedicated lm_sensors -apache2 -eds -gdbm"

ACCEPT_KEYWORDS="~amd64"
```

Au passage, ça sert à quoi le useflag gcc64 ?

----------

## titoucha

Avec eu make.conf comme ça tu dois avoir le répertoire /etc/portage/env bien rempli, il y avait un temps où je faisais comme toi mais le gain par rapport au temps passé était pas super, j'ai abandonné et suis revenu à des flags plus "sages".

----------

## Scullder

 *titoucha wrote:*   

> Avec eu make.conf comme ça tu dois avoir le répertoire /etc/portage/env bien rempli

 

Ca va encore, juste une trentaine de package qui ne passe pas avec ces flags.

----------

## Enlight

Bof à part une utilisation "dommage" de --as-needed, ses ldflags me paraissent pas dérangeants, moi je suis un peu plus extrémiste et j'utilise hashstyle=gnu qui exige le rebuild complet.

Sinon pour les -msse et cie, faut savoir que si march est filtré, ils dégageront avec au niveau de l'ebuild alors on ne force rien du tout, le seul cas utilile que je connaisse c'est l'utilisation de sse3 sur certains athlons64. D'ailleurs tous sont membres de ALLOWED_FLAGS (pas touche à cette variable, hein!!!), ce qui veut dire que c'est pas tous les jours que ça risque de péter quelque chose. après les ftracer et autres fgcse, je n'affirme rien, mais ils me semble qu'ils sont activés avec certains -O levels.

Pour ftree-vectorize j'ai jamais eu d'emm... pour ma part.

Pour les fvisibility, je rejoins Guilc à 100%, quoique j'ai entendu des critiques par rapport à la manière dont KDE l'utilisais, en gros ils marqueraient tout comme hidden, ce qui est a peu près aussi improductif que d'utiliser --as-needed partout.

edit : ah oui je viens de voir le second make.conf ça prends déjà d'autres proportions, déjà t'as 2 fois plusieurs CFLAGS, les CXX sont surement pas mal pour tout péter.

Ah et pour les LDFLAGS, les gnu hash sont censés marcher aussi bien avec -O1 que sans selon le cas. j'aurais aimé le savoir avant :/

----------

## titoucha

 *Enlight wrote:*   

> Bof à part une utilisation "dommage" de --as-needed, ses ldflags me paraissent pas dérangeants, moi je suis un peu plus extrémiste et j'utilise hashstyle=gnu qui exige le rebuild complet.

 

Quel est l'avantage de ce choix de hash, j'ai bien lu l'explication des hash, mais je dois dire que je n'ai pas tout compris   :Embarassed: 

----------

## Enlight

Pfiou alors accroche toi ça va être long, j'en ai chié pour essayer de tout comprendre et de pas trop raconter de conneries.

Alors par où commencer, quand tu codes, tu utilises des noms pour tes fonctions, tes variables etc... ce sont des symboles. Lors de la compilation, le compilateur sait où il place les choses et n'a généralement plus besoin de ces noms, il les garde en général dans une section du format elf pour faire plaisir à ceux qui doivent débugger le code, mais toi et ta gentoo, vous strippez (rayez de la carte) ces noms en général et là si tu lances gdb, je te promets de la joie et du bonheur.

Mais, mais mais mais, si cette fonction ou variable dont tu as besoin n'appartient pas à ton programme, mais à une li... bibliothèque pardon, il faut impérativement garder le nom de la bête, pour que le dynamique linker (in the glibc) puisse aller résoudre tes symboles. en regardant justement dans les sections de ta lib au format elf.

Donc la méthode la plus simple ce serait de faire des comparaisons chaine à chaine, mais si tu dois comparer 5000 chaines de 10 caractères avec 15000 disponibles dans ta lib, sachant que tu est linké à N libs, qui sont elles mêmes liées à d'autres libs (etc...) et que tu ne vas tester ton symbole dans une dépendance d'une lib qu'après avoir échoué dans celle de niveau supérieur, le résultat, c'est que tu lances openoffice, et tu meurs de vieillesse avant d'avoir pu le voir s'afficher.

Donc la première chose qui a été faite pour résoudre ce genre de problèmes, c'est le recours aux hash.

Un hash dc'est tout simplement une fonction qui prends le nom de ta variable, qui applique un affreux calcul (irréversible, car avec le résultat tu ne retrouve jamais le nom) dessus, et qui t'en ressors un entier, qui dans le meilleur des mondes serait unique et donc serait un identifieur aussi parfait que notre nom de symbole, mais qui, en réalité ne l'est pas. Donc quand deux noms nous donnent, une même valeur de hash, ça s'appele une collision. Et donc face à une collision on fait les choses à l'ancienne, on compare les noms complets.

Donc à la base le linkage ça marche de la mabière suivante (pas la moindre option)

Je prends tous mes noms de symboles et je les hash avec le hash dit "sysv" (Pour system V comme dans sysvinit, si vraiment tu veux l'algo, ça peut se faire, mais il est moche et pas très performant)

Ensuite tu mets toutes ces valeurs dans l'ordre croissant et tu choisis arbitrairement un nombre de compartiments. et tu y places les NOMS des symboles dans l'ordre croissant de leur valeur de hash. donc le premier compartiment contient les N symboles au valeurs de hash les plus petites (dans l'ordre croissant), le second, les N suivantes etc... etc...

Maintenant tu fais un index de tes compartiments en faisant un tableau qui prends (toujours dans l'ordre croissant) la valeur du hash du premier symbole de chaque compartiment et tu y asscie un pointeur sur l'entrée de tes compartiments.

A partir de là tu peux faire ta recherche : ton binaire veut foobar, alors le runtime linker va hasher foobar, puis entrer dans le tableau de la lib et rechercher la première valeur à laquelle il est supérieur ou égal, et à partir de là il entre dans le compartiment et fait des comparaisons nom à nom pour voir s'il trouve le symbole.

Donc l'économie c'est que je ne compare mon nom de sybole qu'avec ceux du compartiment et pas ceux de tous les compartiments. Le prix à payer c'est que j'ai quand même des comparaisons d'entiers à faire dans mon tableau auparavant.

A partir de là, Ulrich Drepper (note bien le nom, c'est un de tes dieux), le mainteneur de la Glibc à constaté que comme comparer des entiers est moins couteux que comparer des chaines de caractères, il valait mieux y' aller franco sur le nombre de compartiments, quite à ce que ça fasse grossir notre index et que le binaire soit plus gros (on parle de quelques ko quand même ;o), ça c'est la naissance de -Wl,-O1.

Bon ça c'était la partie facile, pour la petite histoire, Michael Meeks (qui si j'ai bien compris bosse sur OO.o) a voulu améliorer les temps de chargement de ce dernier en allant trifouiller dans binutils et la glibc, ça a donné les patchs Bdirect zdynsort et zdynval. Drepper est completement anti Bdirect, mais les deux autre patchs lui semblaient avoir un peu d'avenir.

Pourtant ça n'a pas abouti, et c'est finalement Jackub Jelinek (un autre dieux sur terre) mainteneur de binutils, lui, qui a sorti les hashval qui t'offrent le choix entre le vieux sysv hash et le gnu hash.

Donc comme tu peux le constater, la fonction de hash n'est plus la même, celle utilisée est celle de Dan Bernstein (auteur de Qmail et djbdns), c'est une fonction simple, jolie, qui a priori défie la logique mathématique, rate tous les test classiques d'évaluation des hash (oui y'a des gens qui y passent leur vie) mais qui en pratique éclate tout ce qui bouge. Nombre de collisions extrèmement bas et fonction très CPU friendly.

Pour info elle marche comme ça : tu initialises le hash à zéro, et pour chaque caractère dans le nom, tu multiplie la valeur du hash par 33 avant d'y ajouter la valeur du caractère.

Bon la partie sérieuse, now!

On garde le principe des compartiments, Mais ce coup ci on a N compartiments de taille N-1 entiers (attends attends, c'est logique tu avs comprendre)

Pour savoir dans quel compartiment on est, toujours le même principe, les A plus petites valeurs dans le premier compartiment, les A suivantes on ira dan le second etc... Mais l'astuce, c'est que je prends la valeur de mon hash modulo le nombre de compartiments (d'où la taille de n-1 du compartiment) et ça me donne la position à laquelle je dois aller regarder dans mon compartiment.

Et donc dans mon compartiment ce que je vais trouver c'est un offset (un pointeur vers une nouvelle structure) ou une valeur : xffffffff qui veut dire qu'il n'y a pas d'objet dans ma lib correspondant à celui que je cherche et que je peux de suite aller voir ailleurs.

Et donc ma structure c'est quoi, c'est tout simplement une liste de tous les hash qui partagent le double critère de taille et de modulo, et là je compare un à un et j'ai mon symbole.

Et donc là si t'as suivi, tu me dit, mais attends c'est n'imp ton truc, on a dit que plusieurs noms pouvaient aboutir à une même valeur de hash et donc dans ce acs faut quand même comparer nom à nom. C'est vrai, mais c'est là toute la magie du nouveau hash aussi, c'est que sur plus de 500 000 symboles testé il n'y a que 4 collisions et ce seulement entre deux noms à chaque fois : cf ici http://sourceware.org/ml/libc-alpha/2006-06/msg00098.html

Enfin dernière chose qui n'enlève rien au charme de ce nouveau hash, les valeurs des symboles sont directement hashées une fois pour toutes dans le binaire qui les réclame, et non plus au moment de la résolution des symboles quand tu lance ton appli, du coup ton cpu peut passer son temps sur le reste o/.

Voilà j'espère que j'ai réussi à rester clair.

----------

## Scullder

Wow, merci pour cette explication claire  :Smile: 

----------

## titoucha

super l'explication, je l'ai même imprimée pour la relire à tête reposée.   :Very Happy: 

Donc si j'ai bien suivi c'est bien plus performant d'utiliser que le hash gnu ?

----------

## Enlight

 *titoucha wrote:*   

> super l'explication, je l'ai même imprimée pour la relire à tête reposée.  
> 
> Donc si j'ai bien suivi c'est bien plus performant d'utiliser que le hash gnu ?

 

Jackup a posté avec le titre "~50% dynamic linking improvement" après je ne sais pas si ce genre de différence c'est avant ou après prelink, toujours est-il que j'estime qu'entre mon hashstyle gnu et prelink, mon premier lancement de firefox commence à être presque décent.

----------

## titoucha

Je vais passer mon système en hash gnu, car je suis déjà content du hash en lui même donc si ça peut être amélioré il n'y a pas à hésiter.

Une dernière question, après je te laisse tranquille   :Wink:  tu utilises quoi comme LDFLAGS ?

PS: encore merci pour ton explication du hash.

----------

## Enlight

Pour l'instant j'utilise : -Wl,-O1 -Wl,--sort-common -Wl,-s -Wl,--hash-style=gnu, mais d'après ce que je viens de lire grace à toi :

la hash-style gnu marcherait aussi bien avec que sans O1, donc autant ne pas l'utiliser afin d'avoir un plus petit binaire.

Avec le hash-style gnu, les symboles dans la section : .dynsym sont triés de manière à refleter l'ordre des listes chainées de la section .gnu-hash, donc je m'interroge sur l'ooportunité d'avoir les symboles des autres sections triées par taille. En tout cas c'est pas comme si l'utiliser ou non allait te changer la vie.

Puis le -s c'est de la parano, c'est justement pour stripper les symboles, ce qui est déjà fait par portage en utilisant strip il me semble.

conclusions LDFLAGS="-Wl,--hash-style=gnu" me parrait être une bonne idée.

NB : pour les collisions de symboles avec le gnu hash, je viens de voir avec objdump -h sur firefox qu'ils créent une section .gnu.conflict, sur ce je me dis qu'il faudra vraiment que je trouve le courage un jour de faire un man elf.

Ah et encore une chose :

J'avais dit que quand tu es linké vers N libs qui elles même sont linkées vers d'autres libs et ainsi de suite :

Ce qu'il faut savoir c'est qu'à la base tu te promènes à travers les tables de hash de toutes ces libs(enfin celles qui suivent une même branche) jusqu'à trouver la bonne. Avec prelink, des la résolution de la lib avec laquelle tu es directement linkée, tu es rediririgé vers la bonne lib de l'arborescence.

donc sans prelink tu fais :

libmachin (échec) -> libtruc (échec) -> libbidule (échec) -> libchose (succès) [nb : on part du principe que ces libs forment une branche de l'arbre des dépendances, chacune est linkée (entre autres) à celle à sa droite]

avec prelink :

libmachin (redirection) -> libchose (succès)

Donc prelink, sailebien.

----------

## titoucha

Ben tu vois avec les flèches j'ai encore mieux compris.   :Wink: 

Pour les LDFLAGS je tournes avec ceux préconisés dans HOWTO et je viens de passer au hash gnu, je suis en pleine compilation.

----------

## apocryphe

Hum... pour le moment ca compile et ca a plutot l'air stable avec:

 *Quote:*   

> 
> 
> CFLAGS="-march=k8 -pipe -O3 -mmx -msse -msse2 -m3dnow -fomit-frame-pointer -fgcse-after-reload -floop-optimize2 -ftracer -ftree-vectorize -DNDEBUG -ffast-math -funroll-loops -freorder-blocks-and-partition"
> 
> CHOST="x86_64-pc-linux-gnu"
> ...

 

j'ai eu sys-libs/db , gmp qui ont eu besoin d'avoir -fPIC ...

et dev-libs/libpcre et app-text/poppler qui ont eu besoin que j'enleve -fvisibility=hidden

jusque la ca va... j'instal kde  :Smile: 

merci tout particulierement a enlight pour ses riches interventions, mais aussi aux autres

----------

## mardi_soir

salut hop 

x86_64-pc-linux-gnu-g++: unrecognized option '-s,--hash-style=gnu'

c'est ti normal ca ?

----------

## titoucha

Non, mais où est la question ?????

----------

## CryoGen

 *mardi_soir wrote:*   

> salut hop 
> 
> x86_64-pc-linux-gnu-g++: unrecognized option '-s,--hash-style=gnu'
> 
> c'est ti normal ca ?

 

Ouep c'est normal, cette option n'est pas pour gcc mais le linker donc le mieux est de le forcer avec -Wl

donc -Wl,-s -Wl,--hash-style=gnu

Merci Enlight qui m'a éclairé il y a un certain temps sur ce détail qui change tout ^_^

----------

## Scullder

-fvisibility=hidden -fvisibility-inlines-hidden -enable-gcc-hidden-visibility, --as-needed...

En fait, si tu as envie de te prendre la tête, utilises ces flags =] Une fois que ton système est contaminé avec ces flags, c'est la grosse m***** =] 

Enfin bon, faut tout casser une fois et se prendre la tête sur la moitié des compil pour se rendre compte que c'est une erreur.

----------

## fb99

dsl de faire le boulet, mais il faut quelque chose de spécial pour utilisé c'est hash-style(au passage merci enlight pour l'explication), parce que moi mon compilateur ne possède pas cette option:

```
gentoo-linux pinko # /usr/i686-pc-linux-gnu/bin/ld --help | grep hash

  --hash-size=<NUMBER>        Set default hash table size close to <NUMBER>
```

ou alors c'est appartir d'un certaine version de gcc genre la dernière 4.3 ??

[EDIT]: merci enlight

----------

## Enlight

faut glibc >= 2.5 et binutils > 2.17

----------

