C скорость сравнения: равно "==" против побитового и "&" - PullRequest
0 голосов
/ 24 января 2020

Предположим, у меня есть целое число, которое является степенью 2, например. 1024:

int a = 1 << 10; //works with any power of 2 no.

Теперь я хочу проверить, совпадает ли другое целое число b с a. Что быстрее / лучше (особенно в слабых встроенных системах):

if (b == a) {}

или

if (b & a) {}

?

Извините, если это вопрос нуба, но не смог не могу найти ответ с помощью поиска.

edit: спасибо за много проницательных ответов. Я мог бы выбрать только один из них, но все они приветствуются.

Ответы [ 3 ]

4 голосов
/ 24 января 2020

Эти операции даже не эквивалентны, потому что a & b будет false, когда оба значения a и b равны 0. Поэтому я бы предложил express семантику, которую вы хотите (т.е. a == b), и разрешил компилятору оптимизировать.

Если вы тогда измерите , что у вас проблемы с производительностью при с этого момента вы можете начать анализировать / оптимизировать ...

3 голосов
/ 24 января 2020

Короткий ответ таков: это зависит от того, какие вещи вы сравниваете. Однако в этом случае я предполагаю, что вы сравниваете две переменные друг с другом (в отличие от переменной и немедленной, и т. Д. c.)

Этот веб-сайт хотя и довольно старый, изучил, сколько тактовых циклов занимают разные инструкции на платформе x86. Здесь нас интересуют две инструкции: «И» и «CMP» (которые компилятор использует для & и == соответственно). Здесь мы видим, что обе эти инструкции занимают около 1/3 цикла, то есть вы можете выполнить 3 из них в среднем за 1 цикл. Сравните это с инструкцией "DIV", для выполнения которой (в 1996 году) потребовалось 23 цикла.

Однако здесь пропущена одна важная деталь. Инструкция «И» не достаточна для завершения искомого поведения. На самом деле, краткая компиляция на x86_64 предполагает, что вам нужны и инструкции «И», и «ТЕСТ» для версии «&», тогда как «==» просто использует инструкцию «CMP». Поскольку все эти инструкции эквивалентны в IP C, «==» будет на самом деле немного быстрее ... с 1996 года.

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

Как отмечалось выше, хотя, даже если у вас есть степень 2, эти инструкции все еще не эквивалентно, так как он не работает для 0. Ну ... Я думаю, технически ноль НЕ является степенью 2. :) Однако, если вы хотите его раскрутить, используйте "==".

3 голосов
/ 24 января 2020

ЦП X86 устанавливает флаг в соответствии с тем, как результат любой операции сравнивается с нулем.

Для == ваш компилятор будет использовать специальную инструкцию сравнения или вычитание, установив этот флаг в оба случая. if() затем реализуется с помощью перехода, который является условным для этого бита.

Для & используются другие инструкции, логические побитовые и инструкции. Это тоже устанавливает флаг соответствующим образом. Итак, снова, следующая инструкция будет условной ветвью.

Итак, вопрос сводится к: Есть ли разница в производительности между вычитанием и побитовой передачей и инструкцией? И ответ "нет" на любой вменяемой архитектуре. Обе инструкции используют один и тот же ALU, обе устанавливают одинаковые флаги, и этот ALU обычно предназначен для выполнения вычитания за один тактовый цикл.


Итог: пишите читаемый код и не пытайтесь микрооптимизировать то, что нельзя оптимизировать.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...