8
votes

Combinaison constante dans l'optimisation des compilateurs

J'ai un fichier d'en-tête contenant beaucoup de petites fonctions en ligne. La plupart d'entre eux arrivent à avoir des données constantes. Étant donné que ces fonctions sont critiques de performance, la manière dont ils traitent les constantes devient importante. AFAIK Il existe deux façons de se référer aux constantes:

1) les définir dans un fichier source séparé qui est ultérieurement lié à l'application. P>

2) Définissez les constantes en place. P>

Je choisirais ce dernier moyen parce qu'il est plus maintenu. Cependant, il pourrait être plus lent si le compilateur n'oblise pas des milliers de constantes égales créées par inlinisation. P>

La question: strong> p>

compilateur combiner ces constantes égales? En particulier, laquelle des méthodes suivantes sera utilisée? P>

1) combinant des constantes égales à travers l'unité de compilation.
2) Combinaison de constantes égales sur le module de liaison (programme entier ou bibliothèque) 3) Combinant les constantes avec Toutes les données constantes statiques em> ont le même motif de bits et remplissent les exigences d'alignement de l'unité de compilation ou du programme entier. P>

J'utilise un compilateur moderne (GCC4.5). P>

Je ne suis pas un expert en assembleur, je ne pouvais donc pas répondre à cette question moi-même en utilisant plusieurs tests simples :) p>

EDIT: p>

Les constantes sont assez grandes (la plupart d'entre eux au moins 16 octets), le compilateur ne peut donc pas leur faire des valeurs immédiates. p>

EDIT2: fort> p>

EXEMPLE DU CODE STRT> P>

Celui-ci utilise la constante mise en place: P>

float_4 sign(float_4 a)
{
    const __attribute__((aligned(16))) float mask[4] = { //I use a macro for this line
        0x80000000, 0x80000000, 0x80000000, 0x80000000};
    const int128 mask = load(mask);
    return b_and(a, mask);
}


10 commentaires

Qu'entendez-vous par «définir les constantes en place»? Comme const int i = 5; ?


Oui. En disant constante, je veux dire des données indépendantes des arguments de la fonction.


Je ne suis pas un expert sur GCC, mais la plupart des compilateurs ne combinent pas du tout des littéraux Conscons, à moins qu'ils ne soient littéraux strings. En outre, un Const Littéral est généralement intégré au code comme une valeur immédiate. Il appartient au Comiler de faire respecter la const-ness de la valeur une fois qu'elle est chargée dans une variable de mémoire.


Je pense que vous êtes confus sur la manière dont l'utilisation des données de Const affecte les performances; par exemple. Dans "car ces fonctions sont critiques de performance, la manière dont ils traitent les constantes devient importante." et dans "Cependant, il pourrait être plus lent si le compilateur n'oblige pas des milliers de constantes égales créées par l'inlinisation".


BTW, Comment activer le stockage de chaîne identique combinant dans VC ++


@Thomasclead. Ces constantes sont assez peu nombreuses, la plupart d'entre elles ont au moins 16 octets. Donc, aucun moyen d'intégrer comme des valeurs immédiates (et cela limiterait sévèrement la performance des décodeurs d'instructions puisqu'ils sont déjà des goulots d'étranglement). Et si GCC ne combine pas des constantes du tout, je suis assez malheureux, car cela signifie que cela signifie beaucoup de travail manuel.


@Fred Nurk: Non, je ne suis pas confondu. En fait, la question est déroutante car elle n'a presque rien à voir avec la Constitution de données (c'est-à-dire le mot clé de coût). Il s'agit simplement de savoir comment le compilateur traite des données en lecture seule.


@ JONS34YP: On dirait que la clarification de la question aiderait vraiment. Avoir un court exemple?


@ JONS34YP ne fusionnant pas les constantes feraient le programme plus gros, mais comment envisagez-vous de le rendre plus lent?


@Jim Balter: Si le compilateur ne fusionne pas de constantes, j'aurais un lot Misses de cache dans le code critique de performance.


3 Réponses :


2
votes

Si vous définissez des constantes dans votre fichier d'en-tête comme ceci: xxx

c'est-à-dire, non seulement la déclaration constante, mais la définition est également visible pour le compilateur lors de la compilation d'une unité de traduction (A fichier source .cc, alors certainement le compilateur le remplace avec une valeur constante dans le code généré, même sans optimisations activées. xxx

remarque comment in FOO (int ) Il fait l'ajout comme Addl 10 $,% EAX , c'est-à-dire dix constante est remplacé par sa valeur. Dans bar (int) , d'autre part, il est d'abord MOVL Douze (% RIP),% EAX pour charger la valeur de Douze de la mémoire dans le registre EAX (le L'adresse sera résolue par la liaison), puis l'addition addl -4 (% RBP),% EAX .

Une version optimisée ressemble à ceci: < Pré> xxx


0 commentaires

8
votes

Selon le GCC ce qui suit L'option fait ce que vous voulez:

-Fartenants-constants

Essayez de fusionner des constantes identiques (constantes de cordes et constantes de points flottants) entre les unités de compilation. Cette option est la valeur par défaut pour la compilation optimisée si l'assembleur et la lieur le supportent. Utilisez -fno-fusion-constantes pour inhiber ce comportement.
Activé aux niveaux -O, -O2, -O3, -Os.


0 commentaires

0
votes

Je ne pense pas qu'il y a des réponses générales à vos questions. J'en donne un pour C uniquement, les règles de C ++ sont différentes.

Cela dépend beaucoup des types de vos constantes. Une classe importante sont des "expressions constantes entier". Celles-ci peuvent être déterminées à la compilation et en particulier être utilisées comme valeurs de "constantes de dénombrement entier". Utilisez que chaque fois que vous pouvez P> xxx pré>

pour de telles constantes, la meilleure chose à faire devait généralement se produire: elles sont réalisées en tant qu'assemblement immédiate. Ils n'ont même pas d'emplacement de stockage, sont directement écrits dans l'assembleur et vos questions n'ont même pas de sens. P>

pour d'autres types de données La question est plus délicate. Essayez d'appliquer qu'aucune adresse de vos «variables qualifiées de const» n'est prise. Cela peut être fait avec le mot-clé p>

register double const something = 5.7;


0 commentaires