Un projet GSoC (Google summer of code) a consisté en l’étude de la parallélisation d’une partie des opérations de GCC, plus particulièrement la partie intermédiaire du compilateur, celle qui s’occupe d’effectuer des optimisations du code indépendantes du processeur ciblé (cette phase se passe sur la représentation intermédiaire GIMPLE). La partie intermédiaire prend une quinzaine de pour cent du temps d’exécution total sur un fichier de test (gimple-match.c, qui représente 100 358 lignes de code C++). Cette phase se passe en deux temps : les optimisations intraprocédurales (optimiser une fonction sans considérer ses interactions avec d’autres) et interprocédurales (avec les interactions, appelées IPA par GCC : inter process analysis).
L’architecture proposée des optimisations se base sur une file producteur-consommateur pour chaque passe d’optimisation, chaque fil d’exécution pouvant prendre un élément dans cette file. De la sorte, si toutes les fonctions à optimiser sont bien équilibrées, on peut espérer diviser le temps d’exécution par le nombre de cœurs disponibles.
Le résultat est assez intéressant : en passant d’un à huit fils d’exécution (le processeur de test disposant de quatre cœurs), le temps complet d’exécution des optimisations est divisé par 2,52 (au vu des parties qui ne sont pas parallélisées, on pouvait espérer un facteur théorique de 2,7). Le temps complet de compilation ne descend que de neuf pour cent. En appliquant la même technique aux optimisations spécifiques aux processeurs (en travaillant au niveau RTL plutôt que GIMPLE), les gains sont plus marqués, cette partie représentant une portion plus importante du temps de compilation : on peut gagner soixante et un pour cent en temps d’exécution en utilisant huit fils d’exécution !
Ces développements ne sont pas encore intégrés dans le code de GCC, mais cela devrait arriver, au vu des gains que l’on peut espérer. Une parallélisation plus fine pourrait encore diminuer les temps de compilation.
Source : présentation GNU Cauldron 2019.