Может ли JIT-компиляция выполняться быстрее, чем создание шаблона времени компиляции?

Недавно я слышал, как многие люди говорят, что JIT-компиляция создает действительно быстрый код, даже быстрее, чем любой статический компилятор. Мне трудно в это поверить, когда дело доходит до шаблонного кода в стиле C ++ STL, но эти люди (как правило, из C # / Java-фона) настаивают, что это действительно так.

У меня такой вопрос: какой тип оптимизации вы можете сделать во время выполнения, но не во время компиляции?

Редактировать: уточнение: меня больше интересуют такие вещи, которые невозможно делать статически, а не типичный случай в любой отрасли.

2

Решение

JIT-компиляторы могут измерять вероятность выполнения условного перехода и соответствующим образом корректировать выдаваемый код. Статический компилятор может сделать это также, но не автоматически; это требует подсказки от программиста.

Очевидно, что это лишь один из многих факторов, но это указывает на то, что возможный чтобы JIT был быстрее при правильных условиях.

2

Другие решения

вещи, которые вы можете сделать во время выполнения

  • проверьте, какие экзотические инструкции существуют (AMD против Intel, ….)
  • определить топологию кэша
  • определить объем памяти
  • количество ядер

и другие вещи, которые я пропустил из списка

Делает ли это все в 10 раз быстрее, нет. Но это, безусловно, дает возможность для оптимизации, которая недоступна во время компиляции (для широко распространенного кода; очевидно, если вы знаете, что он будет только на 3 различных аппаратных конфигурациях, тогда вы можете делать пользовательские сборки и т. Д.)

1

Вопреки тому, что ответ выше претензий:

  1. Специфичные для архитектуры расширения могут легко использоваться статическим компилятором. Например, в Visual Studio есть опция расширения SIMD, которую можно включать и выключать.

  2. Размер кэша обычно одинаков для процессоров данной архитектуры. Например, Intel обычно имеет размер кэша L1 4 КБ, размер кэша L2 32 КБ и размер кэша L3 4 МБ.

  3. Оптимизация по объему памяти будет необходима, только если вы по какой-то причине пишете огромную программу, которая может использовать более 4 ГБ памяти.

  4. Это может быть оптимизация, при которой использование JIT-компилятора действительно полезно. Однако вы можете создать больше потоков, чем имеется ядер, а это означает, что эти потоки будут использовать отдельные ядра в процессорах с большим количеством ядер и просто будут потоками в процессорах с меньшим количеством ядер. Я также думаю, что вполне безопасно предположить, что процессор имеет 4 ядра.

Тем не менее, даже использование многоядерных оптимизаций не делает использование JIT-компилятора полезным, потому что установщик программы может проверить количество доступных ядер и установить соответствующую версию программы, наиболее оптимизированную для числа ядер этого компьютера.

Я не думаю, что JIT-компиляция приводит к лучшей производительности, чем статическая компиляция. Вы всегда можете создать несколько версий своего кода, каждая из которых оптимизирована для конкретного устройства. Единственный тип оптимизации, о котором я могу подумать, может привести к тому, что JIT-код будет быстрее, когда вы получаете ввод, и любой код, который вы используете для обработки, может быть оптимизирован таким образом, чтобы сделать код быстрее для наиболее распространенного случая. (который может обнаружить JIT-компилятор), но медленнее для более редкого случая. Даже тогда вы можете выполнить эту оптимизацию (однако статический компилятор не сможет выполнить эту оптимизацию).

Например, предположим, что вы можете выполнить оптимизацию математического алгоритма, который приводит к ошибке для значений 1-100, но все более высокие числа работают с этой оптимизацией. Вы заметили, что значения 1-100 легко могут быть предварительно рассчитаны, поэтому вы делаете это:

switch(num) {
case 0: {
//code
}
//...until case 100
}

//main calculation code

Однако это неэффективно (при условии, что оператор switch не скомпилирован в таблицу переходов), поскольку регистры 0-100 вводятся редко, поскольку их можно найти мысленно, без помощи компьютера. JIT может обнаружить, что это более эффективно (увидев, что значения в диапазоне 0-100 вводятся редко):

if(num < 101) {
switch(num) {
/...same as other code above
}
}

//main calculation code

В этой версии кода выполняется только 1 if, если наиболее распространенный случай, а не 50 средних if в крайне редком случае (если оператор switch реализован как серия if).

0
По вопросам рекламы [email protected]