Quelle est la distance entre les appels probables et improbables dans le noyau. En cherchant dans la source du noyau, j'ai trouvé ces déclarations.
# define likely(x) __builtin_expect(!!(x), 1)
# define unlikely(x) __builtin_expect(!!(x), 0)
Quelqu'un pourrait-il y jeter un peu de lumière?
Réponses:
Ce sont des conseils de compilation pour GCC. Ils sont utilisés dans les conditions pour indiquer au compilateur si une branche est susceptible d'être prise ou non. Cela peut aider le compilateur à définir le code de manière optimale pour le résultat le plus fréquent.
Ils sont utilisés comme ceci:
Il doit être utilisé avec le plus grand soin (c'est-à-dire sur la base des résultats de profilage de branche réels). Un mauvais indice peut dégrader les performances (évidemment).
Quelques exemples de la façon dont le code peut être optimisé sont facilement trouvés en recherchant
GCC __builtin_expect
. Cet article de blog optimisation gcc: __builtin_expect détaille par exemple un démontage avec celui-ci.Le type d'optimisations qui peut être effectué est très spécifique au processeur. L'idée générale est que, souvent, les processeurs exécutent le code plus rapidement s'il ne se branche / saute pas partout. Plus elle est linéaire et plus les branches sont prévisibles, plus elle s'exécutera rapidement. (Cela est particulièrement vrai pour les processeurs avec des pipelines profonds par exemple.)
Ainsi, le compilateur émettra le code de telle sorte que la branche la plus probable n'impliquera pas de saut si c'est ce que le CPU cible préfère, par exemple.
la source
Décompilons pour voir ce que GCC 4.8 en fait
Sans attendre
Compilez et décompilez avec GCC 4.8.2 x86_64 Linux:
Production:
L'ordre des instructions en mémoire est resté inchangé: d'abord le
printf
, puisputs
leretq
retour.Avec attendre
Remplacez maintenant
if (i)
par:et nous obtenons:
Le
printf
(compilé en__printf_chk
) a été déplacé à la toute fin de la fonction, aprèsputs
et le retour pour améliorer la prédiction de branche comme mentionné par d'autres réponses.C'est donc essentiellement la même chose que:
Cette optimisation n'a pas été effectuée avec
-O0
.Mais bonne chance pour écrire un exemple qui tourne plus vite avec
__builtin_expect
que sans, les processeurs sont vraiment intelligents de nos jours . Mes tentatives naïves sont là .C ++ 20
[[likely]]
et[[unlikely]]
C ++ 20 a normalisé ces éléments intégrés C ++: /programming/51797959/how-to-use-c20s-l probable -unlikely-attribute-in-if-else- statement Ils le feront probablement (un jeu de mots!) faire la même chose.
la source