Почему логический оператор короткого замыкания должен быть быстрее

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

В основном логические AND и OR занимают один цикл, тогда как оценка короткого замыкания использует ветвление и может занимать различное количество циклов. Теперь я знаю, что предсказатели ветвлений могут сделать эту оценку эффективной, но я не понимаю, как это быстрее, чем 1 цикл?

Да, если правый операнд является чем-то дорогим, то попытка не оценивать его выгодна. но для простых условий, таких как X & (Y | Z), предполагая, что это атомарные переменные, логические операторы без короткого замыкания, вероятно, будут работать быстрее. Я прав?


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


person M.kazem Akhgary    schedule 26.12.2017    source источник
comment
Конечно, это не новая мысль, есть несколько связанных ответов, которые на самом деле связаны на боковой панели, и об этом знают и компиляторы - там короткое замыкание && фактически реализовано без короткого замыкания.   -  person harold    schedule 26.12.2017
comment
@гарольд, приятно знать. так что мои предположения были верны. хорошо, что компиляторы могут позаботиться об этом.   -  person M.kazem Akhgary    schedule 26.12.2017
comment
и/или операции занимают более одного цикла, конвейер пытается усреднить все до одного цикла. Точно так же ветки и прогнозирование ветвлений, буферы предварительной выборки и т. д. пытаются получить необходимые данные близко к каналу, чтобы избежать заметных задержек.   -  person old_timer    schedule 27.12.2017
comment
вы отметили язык ассемблера, какой набор инструкций вам нужен?   -  person old_timer    schedule 27.12.2017


Ответы (1)


Это очень поздно, но, поскольку на этот вопрос еще нет ответа (...), я собираюсь попробовать.

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

Оператор короткого замыкания требует, чтобы A и THEN B оценивались, а B не оценивался в случае, если a ложно. Это возвращает нас к ветвям и очистке конвейера ЦП из-за спекулятивного выполнения. Это может стать/становится более дорогостоящим, чем больше условий необходимо проверить последовательно. С другой стороны, это может стать дешевле при операциях без короткого замыкания, поскольку ЦП могут оценивать множество инструкций за один и тот же такт благодаря наличию нескольких физических ALU/FPU/AGU и т. д.

И чтобы понять это, давайте рассмотрим простейший случай в ассемблере:

a && b: 

cmp    a, 0
jne    LABEL_A
---more code---
LABEL_A:
cmp    b, 0
jne    RETURN_LABEL
 ---more code--- 

в отличие от... (при условии, что такие инструкции, как setb, использовались для фиксации до [0, 1])

a & b 

and   a, a, b
cmp   a, 0
jne   RETURN_LABEL
---more code---

Это должно быть очевидно в самой результирующей сборке. Но да, вы правы, говоря, что вам определенно следует использовать короткое замыкание, чтобы избежать дорогостоящего вычисления B в случае, если A ложно. Но даже тогда ЦП все равно может спекулятивно выполнить тест для B. Так что в основном, очень просто говоря, вы можете только усугубить ситуацию, используя операторы короткого замыкания (sic !!!!!).

person MrUnbelievable92    schedule 13.12.2020