Является ли оператор неравенства более быстрым, чем оператор равенства?

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

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

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

10 ответов


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


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

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

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

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


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

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


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

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

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


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

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


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

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


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

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

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

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


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

в алгоритмах поиска (а сортировку можно считать расширением поиска) чаще используются операторы типа "

в любом случае они принимают o(длина слова) количество битовых сравнений, хотя, если длина слова


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

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

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


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

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

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