Является ли оператор неравенства быстрее, чем оператор равенства? - PullRequest
53 голосов
/ 23 июня 2009

Я знаю, что это микрооптимизация, поэтому прошу из чистого любопытства.

Логически, микропроцессору не нужно сравнивать все биты обоих операндов оператора равенства для определения результата «ЛОЖЬ».

Обратите внимание, что это связано с программированием, поскольку оно влияет на скорость выполнения программы.

Ответы [ 10 ]

47 голосов
/ 23 июня 2009

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

29 голосов
/ 23 июня 2009

Это зависит от вашей платформы, но в целом он будет работать одинаково.

Например, на X86 вы можете увидеть это, посмотрев, как работает сборка. Проверьте операции потока управления сборкой X86 - независимо от того, выполняете ли вы равенство или неравенство, это делается в виде 2 операций.

Сначала выполняется операция CMP (сравнение). Затем вы проверяете, равны ли сравнения, не равны и т. Д. Это просто проверка результатов сравнения - в обоих случаях вы выполняете 2 операции.

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

12 голосов
/ 23 июня 2009

Похоже, вам следует прочитать Справочное руководство по оптимизации архитектур Intel 64 и IA-32 .

Найдите в инструкциях, которые вы используете, «Задержка конвейера» и «Задержка конвейера». Достаточно сказать, что все, что вы делаете с целыми числами, занимает около 1 такта (4 миллиарда из них в секунду). Чтение данных из памяти может занять 100-1000 в зависимости от объема данных, с которыми вы работаете. Гораздо важнее.

10 голосов
/ 23 июня 2009

Сравнение обычно выполняется как вычитание, которое игнорирует результат. Сумматор в ЦП будет работать на всех битах одновременно, так что это операция с постоянным временем.

Тогда равенство просто определяет, равен ли выход 0. В x86 есть флаги, которые устанавливаются в результате сравнения, а ветвление выполняется с помощью jz или jnz (переход в ноль, переход в ноль, если не ноль). Так что нет, реальной разницы в скорости не будет.

Другие платформы (такие как ARM и IA64) ведут себя аналогично.

3 голосов
/ 23 июня 2009

Сами инструкции будут выполняться с той же скоростью, что и другие ответы.

Где вы могли бы столкнуться с разницей, было бы в предсказании ветвления или эффектах кэша. Это будет варьироваться от процессора к процессору и от компилятора к компилятору, поэтому обобщения сделать невозможно. Если вы находитесь на том уровне, на котором это будет иметь значение, единственный способ узнать это - попробовать и измерить.

2 голосов
/ 25 июня 2009

Если вы хотите поднять этот вопрос до более общего вопроса, вам следует рассмотреть разумное распределение ответов ИСТИНА и ЛОЖЬ, а также рассмотреть произвольную длину слова, в том числе более длинную, чем регистр.

В алгоритмах поиска (а сортировку можно считать продолжением поиска) чаще используются такие операторы, как «<» или «<=», чем «==». Это связано с тем, что распределение результатов от оператора «==» имеет тенденцию сильно отклоняться в сторону «ложного», и, следовательно, они имеют низкую энтропию (то есть низкий выход информации) на выполнение. Это означает, что они должны выполняться больше раз, чтобы получить одну и ту же информацию - свидетельствуйте о линейном поиске. </p>

В любом случае они берут O (длина слова) числа битовых сравнений, хотя, если длина слова <= длина регистра, сравнения выполняются параллельно, возможно с небольшой задержкой для переноса-распространения. (На самом деле, как мне кажется, в типичном неравном случае любое сравнение может остановиться на первом неравном бите, и если вероятность равенства достаточно мала, это может произойти довольно рано.) </p>

2 голосов
/ 23 июня 2009

Есть несколько незначительных случаев, когда это может иметь некоторый эффект.

На процессорах ARM (для 32-битной архитектуры / архитектуры без большого пальца (ISA)) все инструкции являются условными. Иногда вы можете избежать внутреннего цикла, имеющего одну ветвь (от конца до начала), несмотря на множество условий. В некоторых случаях, имеющих логическое сравнение (TEQ), мешает немного флагов (влияет на отрицательные (N) и ноль (Z), но не на перенос (C) или переполнение (V)), позволяет волосатому коду избежать инструкции перехода (неиспользованный).

И наоборот, IIRC (я никогда не программировал его, но смотрел на результаты компилятора C более десяти лет назад). 68000 имеет буквальную инструкцию EOR / XOR только для регистра D4. Таким образом, арифметическое сравнение, вероятно, будет лучше (хотя вы все равно можете игнорировать посторонние флаги - дело в том, что набор инструкций немного нерегулярный).

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

2 голосов
/ 23 июня 2009

Операция сравнения происходит по переднему (или, возможно, падающему) фронту тактового сигнала микропроцессора. Затем следующая операция происходит в следующем тактовом цикле. Таким образом, с точки зрения скорости выполнения, равенство и неравенство занимают одинаковое количество времени почти для каждого процессора на рынке сегодня.

Я говорю почти , потому что я помню чтение о некоторых процессорах, которые должны были быть не основанными на часах, а основанными на времени работы, поэтому, если действительно операция сравнения была быстрее, чем операция добавления, Набор n сравнений займет меньше времени, чем n . Но я на 99% уверен, что это был какой-то исследовательский проект, а не коммерческий продукт:)

1 голос
/ 25 июня 2009

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

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

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

1 голос
/ 23 июня 2009

Время, необходимое для сравнения, как это обычно составляет один тактовый цикл.

32-битный процессор будет выполнять все 32 бита одновременно; 64-битный будет делать 64 битов одновременно.

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

...