Подтвердить что ты не робот

Сдвиговые биты vs умножаются в PHP

У меня есть следующий код:

<?php
$start = 1;

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

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

Выводится:

0.14027094841003

0.12061500549316

Я нашел в Интернете вопрос о собеседовании Google (который я хотел бы подать заявку на разработчика, но я понимаю, что не могу), и один из вопросов спросил, что самым быстрым способом было умножить число. Моя первая мысль заключалась в использовании знака *, поэтому я его протестировал.

Мой вопрос в том, почему смещение битов происходит быстрее, чем умножение?

4b9b3361

Ответ 1

Поскольку смещение бит - это то, что компьютер делает все время в аппаратном обеспечении, это не требует больших усилий для процессора. Умножение произвольных чисел является чем-то более сложным, потому что это невозможно сделать с помощью простого смещения битов, но требует реальной работы. Умножение маленького целого на 4 происходит как операция, которая идентична сдвигу слева на 2. Но даже если компилятор/среда выполнения/ЦП оптимизирует эту операцию до сдвига бит, некоторый код сначала должен признать, что он может быть оптимизирован таким образом, что больше работы, чем просто бит сдвига.

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

Ответ 2

Поскольку бит-сдвиг - это операция, которая может быть реализована непосредственно в аппаратном обеспечении, тогда как аппаратное обеспечение редко выполняет операции умножения, реализованные непосредственно. Умножение на две силы может быть достигнуто с помощью нескольких простых логических затворов, тогда как умножение на произвольные мультипликаторы требует, по крайней мере, нескольких умножений по степеням двух плюс добавочная операция, уложенная друг на друга (5 = 2 * 2 + 1). Я не знаю, реализует ли PHP-язык операцию переключения, используя любые низкоуровневые вызовы, но я был бы удивлен, если это не так.

Источник: многолетний опыт + образование в области информатики

Ответ 3

На процессорах Intel Sandybrigde кажется смену с непосредственными затратами около 1 такта, в то время как умножение занимает около 3-4 циклов. По-видимому, на всю производительность программы влияет большее количество факторов, чем просто сырое умножение, но этого достаточно, чтобы сделать разницу. Большинство компиляторов в эти дни оптимизируют умножение на константы 2 ^ n на смены (авторы компилятора любят оптимизировать ваш код:)), но, возможно, интерпретатор PHP этого не делает.