Compilateur JIT pour C, C ++ et les goûts

33

Existe-t-il un compilateur juste à temps pour les langages compilés, tels que C et C ++? (Les premiers noms qui me viennent à l'esprit sont Clang et LLVM! Mais je ne pense pas qu'ils le supportent actuellement.)

Explication:

Je pense que le logiciel pourrait tirer parti des retours d'informations sur les profils d'exécution et d'une recompilation optimisée de manière agressive des zones sensibles au moment de l'exécution, même pour les langages compilés sur machines tels que C et C ++.

L'optimisation guidée par le profil fait le même travail, mais à la différence un JIT serait plus flexible dans différents environnements. Dans PGO, vous exécutez votre binaire avant de le publier. Une fois que vous l'avez publié, il n'utiliserait aucun retour d'informations sur l'environnement / les entrées collectées lors de l'exécution. Par conséquent, si le modèle d'entrée est modifié, il en résulte une dégradation des performances. Mais JIT fonctionne bien même dans ces conditions.

Cependant, je pense qu’il est controversé de savoir si l’ECM compilant l’avantage lié aux performances dépasse ses propres frais généraux.

Ebrahim Mohammadi
la source
1
Ressource hors sujet hors site.
DeadMG
1
Je ne suis pas sûr que cela corresponde à la question, mais je pense que le package Cxx dans le langage Julia est utile . Il vous propose une invite C ++ interactive similaire à celle décrite dans la réponse @ PhilippClaßen.
Antonello
GCC 9 a maintenant un compilateur jit gcc.gnu.org/onlinedocs/jit/intro/index.html
user3071643 Le

Réponses:

33

[Voir l'historique des modifications pour une réponse très différente, à présent obsolète.]

Oui, il existe deux compilateurs JIT pour C et / ou C ++.

Cling (comme vous pouvez le deviner dans le jeu) est basé sur Clang / LLVM. Il agit comme un interprète. Autrement dit, vous lui donnez du code source, vous lui donnez une commande et il s'exécute. L'accent est mis ici principalement sur la commodité et la compilation rapide, pas sur l'optimisation maximale. En tant que tel, bien que techniquement une réponse à la question elle-même, cela ne convient pas vraiment à l'intention du PO.

Une autre possibilité est NativeJIT . Cela correspond à la question un peu différemment. En particulier, il n'accepte pas le code source C ou C ++, ne le compile pas et ne l'exécute pas. C'est plutôt un petit compilateur que vous pouvez compiler dans votre programme C ++. Il accepte une expression qui est fondamentalement exprimée sous la forme d'un EDSL dans votre programme C ++ et génère le code machine réel à partir de celui-ci, que vous pouvez ensuite exécuter. Cela correspond beaucoup mieux à un cadre dans lequel vous pouvez compiler la plupart de votre programme avec un compilateur normal, tout en ayant quelques expressions que vous ne saurez pas avant l'exécution, que vous voulez exécuter avec quelque chose qui approche de la vitesse d'exécution optimale.

En ce qui concerne l’intention apparente de la question initiale, je pense que l’essentiel de ma réponse reste valable: même si un compilateur JIT peut s’adapter, par exemple, à des données qui varient d’une exécution à l’autre, ou qui varient même de manière dynamique au cours d’une exécution unique, la réalité est que cela fait relativement peu de différence, du moins en règle générale. Dans la plupart des cas, l'exécution d'un compilateur au moment de l'exécution signifie que vous devez renoncer à un peu d'optimisation. Par conséquent, le mieux que vous puissiez espérer, c'est qu'il soit presque aussi rapide que ce qu'un compilateur traditionnel produirait.

Bien qu'il soit possible de postuler des situations dans lesquelles les informations disponibles pour un compilateur JIT pourraient lui permettre de générer un code nettement supérieur à celui d'un compilateur conventionnel, il semble en pratique que cela se produise dans la pratique (et dans la plupart des cas où j'ai pu vérifier c’est vraiment dû à un problème dans le code source, pas au modèle de compilation statique).

Jerry Coffin
la source
1
Pourquoi les JIT n'enregistrent-ils pas un fichier de type cache afin qu'ils puissent ignorer de tout réapprendre à partir de zéro?
JohnMudd
3
@JohnMudd: Je soupçonne que le raisonnement est la sécurité. Par exemple, modifiez le code mis en cache, puis au prochain démarrage de la VM, il exécutera le code que j'ai mis là au lieu de ce qu'il a écrit ici.
Jerry Coffin
4
OTOH, si vous pouvez modifier les caches, vous pouvez également modifier les fichiers source.
user3125367
1
@ user3125367: Oui, mais dans de nombreux cas, le compilateur effectue diverses vérifications de type et peut être ignoré si vous chargez du code compilé directement à partir du cache. Cela dépend évidemment de JIT - Java effectue beaucoup de travail d’application lors du chargement d’un fichier .class (compilé), mais beaucoup d’autres en font beaucoup moins (presque pas, dans de nombreux cas).
Jerry Coffin
11

Oui, il existe des compilateurs JIT pour C ++. Du point de vue des performances pures, je pense que l’optimisation guidée par le profil (PGO) est toujours supérieure.

Cependant, cela ne signifie pas que la compilation JIT n'est pas encore utilisée dans la pratique. Par exemple, Apple utilise LLVM en tant que JIT pour son pipeline OpenGL. C'est un domaine dans lequel vous disposez de beaucoup plus d'informations au moment de l'exécution, ce qui peut être utilisé pour supprimer beaucoup de code mort.

Une autre application intéressante de JIT est Cling, un interpréteur C ++ interactif basé sur LLVM et Clang: https://root.cern.ch/cling

Voici un exemple de session:

[cling]$ #include <iostream>
[cling]$ std::cout << "Hallo, world!" << std::endl;
Hallo, world!
[cling]$ 3 + 5
(int const) 8
[cling]$ int x = 3; x++
(int) 3
(int const) 3
[cling]$ x
(int) 4

Ce n'est pas un projet de jouet, mais il est effectivement utilisé au CERN, par exemple, pour développer le code du grand collisionneur de hadrons.

Philipp Claßen
la source
7

C ++ / CLI est jeté. Certes, C ++ / CLI n'est pas C ++ mais c'est assez proche. Cela dit, JIT de Microsoft ne fait pas les optimisations super intelligentes / mignonnes basées sur le comportement d'exécution que vous demandez, du moins pas à ma connaissance. Donc, cela n'aide vraiment pas.

http://nestedvm.ibex.org/ transforme MIPS en bytecode Java qui serait ensuite jeté. Le problème avec cette approche de votre question est que vous perdez une grande partie de l’information utile au moment où elle parvient à l’ECM.

Logan Capaldo
la source
2

Tout d'abord, je suppose que vous voudriez un jit de traçage plutôt qu'un jit de méthode.

La meilleure approche consiste à compiler le code dans llvm IR, puis à ajouter du code de traçage avant de produire un exécutable natif. Une fois qu'un bloc de code est suffisamment utilisé et une fois que suffisamment d'informations sur les valeurs (et non les types comme dans les langages dynamiques) des variables ont été collectées, le code peut être recompilé (à partir de l'IR) avec des gardes basés sur les valeurs des variables.

Je crois me souvenir qu’il ya eu quelques progrès dans la fabrication de j / c ++ jit in clang sous le nom libclang.

dan_waterworth
la source
1
Autant que je sache, libclang est la plupart des fonctionnalités de clang factorisées en tant que bibliothèque. vous pouvez donc l'utiliser pour analyser le code source afin de créer une coloration syntaxique sophistiquée, des lints, une navigation dans le code, etc.
Javier
@ Javier, ça sonne bien. Je pense qu'il y avait une fonction dans la bibliothèque qui prenait un caractère constant * de code source et produisait llvm ir, mais en pensant maintenant, il est probablement préférable de jit basé sur l'ir plutôt que sur la source.
dan_waterworth