Компілятор JIT для C, C ++ тощо


33

Чи існує якийсь своєчасний компілятор для компільованих мов, таких як C і C ++? (Перші імена, які спадають на думку, - це Кланг та LLVM! Але я не думаю, що вони зараз це підтримують.)

Пояснення:

Я думаю, що програмне забезпечення могло б отримати користь від зворотного зв’язку під час профілювання та агресивно оптимізованої перекомпіляції гарячих точок під час виконання, навіть для мов компільованого на машині типу C та C ++.

Профільована оптимізація виконує аналогічну роботу, але з різницею JIT був би більш гнучким у різних середовищах. У PGO ви запускаєте свій двійковий файл до його випуску. Після того як ви випустили його, він не використовуватиме зворотних зв'язків / входів, зібраних під час виконання. Таким чином, якщо шаблон введення буде змінено, це зонд виконання покарання. Але JIT працює добре навіть у тих умовах.

Однак я думаю, що це суперечливо, якщо вигода від компіляції JIT з перевагою продуктивності переважає власні накладні витрати.


1
Ресурс поза темою.
DeadMG

1
Не впевнений, чи відповідає це питання, але для перспективності використання я вважаю корисним пакет Cxx на мові Julia .. він дає вам інтерактивне підказку C ++, подібне до описаного у відповіді @ PhilippClaßen.
Антонелло

GCC 9 тепер має компілятор jit gcc.gnu.org/onlinedocs/jit/intro/index.html
user3071643

Відповіді:


33

[Дивіться історію редагування для зовсім іншої відповіді, яка в основному застаріла.]

Так, є кілька компіляторів JIT для C та / або C ++.

CLing (як ви могли здогадатися з гри) заснований на Clang / LLVM. Він діє як перекладач. Тобто ви даєте йому якийсь вихідний код, даєте команду для його запуску, і він запускається. Акцент тут робиться насамперед на зручності та швидкому складанні, а не на максимальній оптимізації. Таким чином, хоча технічно це відповідь на саме запитання, це не дуже відповідає наміру ОП.

Інша можливість - NativeJIT . Це підходить до питання дещо інакше. Зокрема, він не приймає вихідний код C або C ++, а компілює його та виконує. Скоріше, це невеликий компілятор, який можна скласти у свою програму C ++. Він приймає вираз, який в основному виражається як EDSL у вашій програмі C ++, і генерує з цього фактичний машинний код, який ви можете потім виконати. Це набагато краще відповідає рамці, де ви можете скласти більшу частину програми за допомогою звичайного компілятора, але у вас є кілька виразів, про які ви не знатимете до часу виконання, які ви хочете виконати з чимось наближенням до оптимальної швидкості виконання.

Що стосується очевидного наміру оригінального запитання, я вважаю, що основний момент моєї оригінальної відповіді все ще стоїть: хоча компілятор JIT може адаптуватись до таких речей, як дані, що змінюються від одного виконання до іншого, або навіть динамічно змінюються під час одного виконання, реальність така, що це робить порівняно незначну різницю, принаймні як загальне правило. У більшості випадків запуск компілятора під час виконання означає, що вам потрібно відмовитись від оптимізації, тому найкраще, на що ви навіть сподіваєтесь, - це те, що він настільки ж швидкий, як і звичайний компілятор.

Хоча можливо постулювати ситуації, коли інформація, доступна компілятору JIT, могла б дати йому можливість генерувати значно кращий код, ніж звичайний компілятор, випадки цього на практиці здаються досить незвичними (і в більшості випадків, коли мені вдалося перевірити це відбувається, це було насправді пов’язано з проблемою у вихідному коді, а не зі статичною моделлю компіляції).


1
Чому JIT не зберігають файл, схожий на кеш, щоб вони могли пропустити повторно все з нуля?
ДжонМудд

3
@JohnMudd: Я підозрюю, що міркування - це безпека. Наприклад, змініть кешований код, то наступного разу, коли VM запускається, він виконує код, який я кладу туди замість того, що там написав.
Джеррі Труну

4
OTOH, якщо ви можете змінювати кеші, ви також можете змінювати вихідні файли.
user3125367

1
@ user3125367: Так, але у багатьох випадках компілятор робить різні перевірки типів і такі, які можуть бути обійдені, якщо ви завантажуєте компільований код безпосередньо з кеша. Звичайно, залежить від JIT - Java виконує чимало робіт з примусового виконання під час завантаження (компільованого) .class-файлу, але багато інших роблять набагато менше (майже у багатьох випадках).
Джеррі Коффін

11

Так, є компілятори JIT для C ++. З точки зору чистої продуктивності, я думаю, що оптимізація з профілем (PGO) все ще перевершує.

Однак це не означає, що компіляція JIT ще не використовується на практиці. Наприклад, Apple використовує LLVM як JIT для свого конвеєра OpenGL. Це домен, де ви маєте значно більше інформації під час виконання, який можна використовувати для видалення безлічі мертвих кодів.

Ще одне цікаве застосування JIT - це Cling, інтерактивний інтерпретатор C ++ на базі LLVM та Clang: https://root.cern.ch/cling

Ось зразок сеансу:

[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

Це не іграшковий проект, але він фактично використовується в CERN, наприклад, для розробки коду для великого адронного колайдера.


7

C ++ / CLI вирівнюється. Звичайно, C ++ / CLI - це не C ++, але він досить близький. Однак, JIT Майкрософт не робить надзвичайно розумних / симпатичних оптимізацій на основі поведінки, про які ви питаєте, принаймні, не мої знання. Тож це насправді не допомагає.

http://nestedvm.ibex.org/ перетворює MIPS у байт-код Java, який потім буде jitted. Проблема такого підходу з вашого запитання полягає в тому, що ви викидаєте багато корисної інформації до моменту, коли вона потрапить до СТІ.


2

По-перше, я припускаю, що ви хочете відстежувати jit, а не метод jit.

Найкращим підходом було б складання коду до llvm IR, а потім додавання коду відстеження, перш ніж створити власний виконуваний файл. Як тільки блок коду стає достатньо добре використаним і одного разу достатньою інформацією про значення буде зібрано (а не про типи, як у динамічних мовах) змінних, код можна перекомпілювати (з ІЧ) із захисниками на основі значень змінних.

Я, мабуть, пам’ятаю, був певний прогрес у створенні ac / c ++ jit у clang під назвою libclang.


1
AFAIK, libclang - це більшість функцій клаксонів, що використовуються як бібліотека. таким чином, ви можете використовувати його для аналізу вихідного коду для створення складних кольорів синтаксису, підказки, перегляду коду тощо.
Хав'єр

@Javier, це звучить правильно. Я думаю, що в бібліотеці була функція, яка брала const char * вихідного коду і виробляла llvm ir, але, думаючи зараз, напевно, краще джит на основі ir, а не на джерело.
dan_waterworth
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.