Как умножение может быть быстрее, чем сдвиг бит влево? - PullRequest
0 голосов
/ 11 ноября 2018

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

$start = 1;

$timestart = microtime(1);
for ($i = 0; $i < 10000000; $i++) {
    $result2 = $start << 2;
}
echo microtime(1) - $timestart;

$timestart = microtime(1);
for ($i = 0; $i < 10000000; $i++) {
    $result1 = $start * 4;
}
echo microtime(1) - $timestart;
echo "\n";

Поскольку я выполнял его несколько раз и всегда умножение происходило быстрее, чем смещение битов влево.Например:

0.73733711242676

0.71091389656067

Следовательно, либо неверный тест, либо интерпретатор PHP что-то здесь делает.Тест выполняется PHP 7.0.32, работающим в Ubuntu:

PHP 7.0.32-0ubuntu0.16.04.1 (cli) (NTS)

Процессор: Intel (R) Core (TM)) i5-4460 CPU @ 3,20 ГГц

Редактировать:

Выполнение его в коробке Windows, с почти таким же процессором (Intel® Core) (TM) i5-4460S CPU @ 2,90 ГГц) результаты ожидаемые:

0.24960112571716

0.28080010414124

Версия PHP для этого случая другая:

PHP 7.1.19 (cli) (Построен: 20 июня 2018 23:24:42) (ZTS MSVC14 (Visual C ++ 2015) x64)

1 Ответ

0 голосов
/ 11 ноября 2018

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

Asm-версия любого цикла может работать со скоростью 1 за такт (при условии сдвига с фиксированным счетом), поэтому только 100 000 итераций потребуют (на процессоре 3 ГГц) 0,033 мс или 0,000033 секунды, что примерно в 250 раз быстрее, чем ваш PHP раз.


Кроме того, интерпретируемый цикл должен использовать сдвиг счетчика переменных (потому что он не может JIT-компилировать счетчик сдвига в непосредственный в машинном коде), что на самом деле дороже для пропускной способности (3 моп) в Intel Процессоры из-за устаревшего багажа x86 (семантика флага). Процессоры AMD имеют сдвиги в одну моп даже при переменном числе сдвигов. (shl reg, cl против shr reg, imm8). См. инструкция INC против ADD 1: имеет ли это значение? для получения дополнительной информации о том, почему shl reg,cl равно 3 мопам в семействе Sandybridge, и как это может создать ложную зависимость с помощью флагов)

Целочисленное умножение составляет 1 мегапиксель, пропускную способность 1 тактовую частоту, задержку 3 цикла для семейств Intel Sandybridge и AMD Ryzen. Я за 2 часа на AMD Bulldozer-семье, не полностью конвейерной. Так что да, умножение имеет более высокую задержку, но они оба полностью конвейерны для пропускной способности. Ваш цикл отбрасывает результат, поэтому цепочка зависимостей, переносимых циклами, отсутствует, поэтому задержка не имеет значения (и скрыта при выполнении вне очереди).

Но этой незначительной разницы (2 дополнительных мопа) недостаточно, чтобы учесть измеренную разницу. Фактическое смещение или умножение составляет всего 1/250 от общего числа циклов, которые проходит цикл. Вы говорите, что переключение порядка циклов не меняет результат, так что это не просто эффект разогрева, пока ваш процессор не разгонится до максимальной тактовой частоты.

Вы не упомянули, на какой микроархитектуре ЦП вы работаете, но ответ, вероятно, не зависит от того, как декодируются команды сдвига и умножения.

...