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

Как этот код:

var check = 0;

for (var numerator = 0; numerator <= maxNumerator; numerator++)
{
    check += numerator >= 0
           ? numerator - (int) ((numerator * qdi.Multiplier) >> qdi.Shift) * qdi.Number
           : numerator - (int) -((-numerator * qdi.Multiplier) >> qdi.Shift) * qdi.Number;
}

return check;

может работать в 3 раза быстрее, чем этот код:

var check = 0;

for (var numerator = 0; numerator <= maxNumerator; numerator++)
{
    check += numerator >= 0
           ? (int) ((numerator * qdi.Multiplier) >> qdi.Shift)
           : (int) -((-numerator * qdi.Multiplier) >> qdi.Shift);
}

return check;

Первый фрагмент кода выполняет точно такую ​​же операцию быстрого деления ( это умножение, затем сдвиг вправо), но также вычитание и умножение, но JIT-компилятор, похоже, производит более медленный код.

У меня есть код дизассемблирования для каждого доступного.
Более медленный код сдвигает регистр rbx и вычитает 10h из rsp в начале, затем добавляет его обратно и выталкивает rbx в конце, тогда как более быстрый код этого не делает.
Более медленный код также использует регистр r11 для большинства вещей, где более быстрый код использует rdx.

Есть идеи?

6
задан Keith 13 May 2011 в 00:18
поделиться