Почему механизм выполнения LLVM быстрее, чем скомпилированный код?

У меня есть компилятор, предназначенный для LLVM, и я предлагаю два способа запустить код:

  1. Запустить его автоматически. В этом режиме код компилируется в LLVM и используется ExecutionEngine JIT для компиляции его в машинный код на лету и запуска без создания выходного файла.
  2. Скомпилируйте и запустите отдельно. В этом режиме выводится файл LLVM .bc, который я оптимизирую вручную (с opt ), скомпилировать в собственную сборку (с llc ) скомпилировать в машинный код и связать (с gcc ) и запустить.

Я ожидал, что подход №2 будет быстрее, чем подход №1 , или, по крайней мере, с той же скоростью, но проведя несколько тестов скорости, я с удивлением обнаружил, что №2 постоянно работает примерно в два раза медленнее. Это огромная разница в скорости.

В обоих случаях используется один и тот же исходный код LLVM. При подходе №1 я еще не потрудился запускать какие-либо проходы оптимизации LLVM (поэтому я ожидал, что это будет медленнее). При подходе № 2 я использую opt с -std-compile-opts и llc с -O3 , чтобы максимизировать оптимизацию, но он не приближается к №1. Вот пример запуска той же программы:

  • # 1 без оптимизации: 11. 833s
  • # 2 без оптимизации: 22.262s
  • # 2 с оптимизацией ( -std-compile-opts и -O3 ): 18.823s

Это ExecutionEngine делать что-то особенное, о чем я не знаю? Есть ли у меня способ оптимизировать скомпилированный код для достижения той же производительности, что и JIT ExecutionEngine?

44
задан mgiuca 13 May 2011 в 07:06
поделиться