0
votes

Combien de gain de vitesse si vous utilisez __inline__?

dans ma compréhension, Inline peut accélérer l'exécution du code, est-ce?

Combien de vitesse pouvons-nous gagner de cela?


6 commentaires

Cela peut varier sauvagement - cela pourrait même monter dans quelques cas. Vous devrez mesurer.


Vous enregistrez la fonction d'appel de la fonction. Donc, pour une fonction complexe, cela n'est pas pertinent, mais pour des fonctions triviales, cela pourrait aller bien environ 90% de son temps d'exécution. La ramification elle-même est souvent chère pour les processeurs modernes (flushing de pipeline, problèmes de mise en cache, etc. PP), il peut donc s'agir d'un grand gain pour l'éviter.


Avez-vous essayé d'écrire un exemple d'exemple simple, de désactiver les optimisations et du calendrier des résultats? De toute façon, il va dépendre beaucoup des circonstances qui sont hors de contrôle de votre programme, telles que l'architecture du processeur.


@Marque. Il ne peut que la même chose que l'appel de la fonction.


Le spécificateur de fonction inline est seulement un indice que le compilateur est autorisé à aligner la fonction. Le compilateur pourrait ne pas le faire de toute façon. Et il peut décider de fonctions en ligne qui sont pas marquées comme en ligne aussi.


En effet, le compilateur est toujours autorisé à aligner un appel de fonction


3 Réponses :


4
votes

déchiré de ici :

oui et non. Parfois. Peut-être.

Il n'y a pas de réponses simples. Les fonctions en ligne peuvent rendre le code plus rapidement, ils pourraient le rendre plus lent. Ils pourraient rendre l'exécutable plus grand, ils pourraient le rendre plus petit. Ils pourraient provoquer des traverser, ils pourraient éviter de battre. Et ils pourraient être, et sont souvent, totalement non pertinents pour accélérer.

Les fonctions inline peuvent le rendre plus rapide : comme indiqué comme indiqué ci-dessus , l'intégration procédurale peut supprimer un tas d'instructions inutiles, ce qui pourrait rendre les choses plus rapidement.

Les fonctions en ligne pourraient le rendre plus lente : trop d'inlinage pourrait provoquer un bloat de code, ce qui pourrait provoquer des systèmes de mémoire virtuelle "de croisement" sur la demande. En d'autres termes, si la taille exécutable est trop grande, le système pourrait passer la majeure partie de son temps à sortir du disque pour aller chercher le prochain morceau de code.

Les fonctions inline peuvent le rendre plus grand : il s'agit de la notion de code de code, comme décrit ci-dessus. Par exemple, si un système comporte 100 fonctions inline, chacune étant étendue à 100 octets de code exécutable et s'appelle à 100 places, c'est une augmentation de 1 Mo. Est-ce que 1 Mo va causer des problèmes? Qui sait, mais il est possible que ces derniers 1 Mo puisse causer le système "thrash" et qui pourrait ralentir les choses.

Les fonctions inline pourraient le rendre plus petit : le compilateur génère souvent plus de code pour appuyer / les registres / paramètres de pop que possible par le corps de la fonction en ligne. Cela se produit avec de très petites fonctions, et il arrive également avec de grandes fonctions lorsque l'optimiseur est capable de supprimer beaucoup de code redondant grâce à l'intégration procédurale - c'est-à-dire lorsque l'optimiseur est capable de rendre la grande fonction petite.

Les fonctions en ligne peuvent provoquer une plancheuse : l'inlinge peut augmenter la taille de l'exécutable binaire, ce qui pourrait provoquer une traversée.

Les fonctions inline peuvent empêcher la batterie : la taille de jeu de travail (nombre de pages à la mémoire à la fois en mémoire) peut diminuer même si la taille exécutable augmente. Lorsque f () appelle g (), le code est souvent sur deux pages distinctes; Lorsque le compilateur intègre la procédure au code de g () dans F (), le code est souvent sur la même page.

Les fonctions en ligne pourraient augmenter le nombre de cache Misses : l'inlinge peut entraîner une boucle interne sur plusieurs lignes du cache de mémoire, ce qui pourrait provoquer une rotation du cache mémoire.

Les fonctions en ligne pourraient diminuer le nombre de cache Misses : l'inlinisation améliore généralement la localité de référence dans le code binaire, ce qui pourrait diminuer le nombre de lignes de cache nécessaires pour stocker le code d'une boucle interne. Cela pourrait finalement provoquer une application liée à la CPU de fonctionner plus rapidement.

Les fonctions en ligne peuvent être sans importance pour la vitesse : la plupart des systèmes ne sont pas liés à la CPU. La plupart des systèmes sont liés à I / O-liés, à la base de données ou à un réseau, ce qui signifie que le goulot d'étranglement de la performance globale du système est le système de fichiers, la base de données ou le réseau. À moins que votre "CPU Compteur" ne soit pas inférieur à 100%, les fonctions en ligne ne rendront probablement pas votre système plus rapidement. (Même dans les systèmes liés à la CPU, en ligne ne vous aidera que lorsqu'il est utilisé dans le goulot d'étranglement lui-même, et le goulot d'étranglement est typiquement en un seul pourcentage du code.)

Il n'y a pas de réponse simple : vous devez jouer avec cela pour voir ce qui est le mieux. Ne vous contentez pas de réponses simplistes comme "N'utilisez jamais les fonctions intégrées" ou "toujours utiliser des fonctions en ligne" ou "utilisez des fonctions en ligne si et uniquement si la fonction est inférieure à N lignes de code." Ces règles à une taille unique - toutes les règles peuvent être faciles à écrire, mais elles produiront des résultats sous-optimaux.

Copyright (c) Marshall Cline


2 commentaires

En bout de ligne: si vous ne savez pas comment l'utiliser - ne l'utilisez pas.


comme indiqué ci-dessus, intégration procédurale .... ci-dessus doit avoir un lien !!



2
votes

Utilisation de Inline fait que le système utilise le système Modèle d'évaluation de substitution , mais cela n'est pas garanti d'être utilisé tout le temps. Si cette option est utilisée, le code généré sera plus long et peut être plus rapide, mais si certaines optimisations sont actives, le modèle de dépouillement n'est pas plus rapide et non plus rapidement.


0 commentaires

1
votes

La raison pour laquelle j'utilise Inline code> Spécificateur de fonction (spécifiquement, en ligne statique code>) n'est pas à cause de "vitesse", mais parce que

  1. statique code> Partie indique au compilateur La fonction est visible uniquement dans l'unité de traduction actuelle (le fichier actuel étant compilé et inclus fichiers d'en-tête) p> li>

  2. inline code> Partie indique au compilateur, il peut inclure la mise en œuvre de la fonction sur le site d'appel, si elle veut P> LI>

  3. statique en ligne code> indique au compilateur qu'il peut ignorer complètement la fonction si elle n'est pas utilisée du tout dans l'unité de traduction actuelle p>

    (spécifiquement, le compilateur que j'utilise le plus avec les options que j'utilise, gcc -wall code>, émet un avertissement si une fonction marquée statique code> n'est pas utilisée; mais ne délivrera pas un avertissement si une fonction marquée statique en ligne code> n'est pas utilisée.) p> li>

  4. Statique Inline CODE> nous dit des humains que la fonction est une fonction d'assistance de type macro, ajoutant ainsi un vérificateur de type au même comportement que Macro. P> Li> ol>

    Ainsi, à mon avis, l'hypothèse que inline code> a quelque chose à voir avec vitesse em> en soi, est incorrecte. Répondre à la question indiquée avec une réponse directe serait trompeuse. P>


    dans mon code, vous les voyez associés à certaines structures de données ou parfois de variables globales. P>

    Exemple typique est quand je veux mettre en place un Xorshift Pseudorandom Numberatrice générateur dans mon propre code C: P > xxx pré>

    le statique uint64_t prng_state = 1; code> signifie que prng_state code> est une variable de type uint64_t cod>, Visible uniquement dans l'unité de compilation actuelle et initialisée à 1. La fonction prng_u64 () code> renvoie un entier de pseudorandom de 64 bits non signé. Cependant, si vous n'utilisez pas prng_u64 () code>, le compilateur ne générera pas de code pour celui-ci non plus. P>

    Un autre cas d'utilisation typique est lorsque j'ai des structures de données, et ils ont besoin d'accessoires les fonctions. Par exemple, P>

    #ifndef   GRID_H
    #define   GRID_H
    #include <stdlib.h>
    
    typedef struct {
        int            rows;
        int            cols;
        unsigned char *cell;
    } grid;
    #define  GRID_INIT { 0, 0, NULL }
    
    #define  GRID_OUTSIDE -1
    
    static inline int grid_get(grid *const g, const int row, const int col)
    {
        if (!g || row < 0 || col < 0 || row >= g->rows || col >= g->cols)
            return GRID_OUTSIDE;
        return g->cell[row * (size_t)(g->cols) + col];
    }
    
    static inline int grid_set(grid *const g, const int row, const int col,
                               const unsigned char value)
    {
        if (!g || row < 0 || col < 0 || row >= g->rows || col >= g->cols)
            return GRID_OUTSIDE;
        return g->cell[row * (size_t)(g->cols) + col] = value;
    }
    
    static inline void grid_init(grid *g)
    {
        g->rows = 0;
        g->cols = 0;
        g->cell = NULL;
    }
    
    static inline void grid_free(grid *g)
    {
        free(g->cell);
        g->rows = 0;
        g->cols = 0;
        g->cell = NULL;
    }
    
    int grid_create(grid *g, const int rows, const int cols,
                    const unsigned char initial_value);
    
    int grid_load(grid *g, FILE *handle);
    
    int grid_save(grid *g, FILE *handle);
    
    #endif /* GRID_H */
    


5 commentaires

Au point 3: je pense que "statique" seul suffit, c'est que le compilateur peut sauter la fonction s'il est inutilisé


@CTX: gcc -wall émettra un avertissement si une fonction statique n'est pas utilisée, mais pas sur si une fonction statique en ligne n'est pas utilisée. . Devrais-je clarifier cela au point?


Pourquoi pas? C'est nouveau pour moi;) Je me demande, quelle est la raison pour le comportement d'avertissement différent?


@CTX: J'utilise toujours -wall . Il active -wunused-fonction : "warn à chaque fois qu'une fonction statique est déclarée mais non définie ou une fonction statique non intégrée n'est pas utilisée."


Quant pourquoi on voudrait que l'avertissement avec une fonction statique mais non intégrée, et non avec une fonction en ligne statique, est probablement parce qu'ils pensent dans le même sens que je le fais sur ces quatre points. Ou peut-être existe-t-il un libellé standard obscur C concernant les fonctions inline et non en ligne avec une liaison interne que j'ai manquée, cela rend l'avertissement utile. Ou peut-être que les gens de GCC ont une autre raison, je ne sais pas. Mais j'aimerais penser que la plupart des programmeurs vétéran C sont d'accord avec ces points. :)