Преимущества использования оценки короткого замыкания

boolean a = false, b = true;
if ( a && b ) { ... };

В большинстве языков b не будет оцениваться, потому что a является ложным, поэтому a && b не может быть правдой. Мой вопрос: не будет ли короткое замыкание медленнее с точки зрения архитектуры? В конвейере вы просто останавливаетесь, ожидая, чтобы получить результат a, чтобы определить, следует ли оценивать b или нет? Было бы лучше делать вложенные ifs вместо этого? Помогает ли это?

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

Хорошо, я думаю, что другой пример, возможно, объяснит, откуда мой друг. Он полагает, что, так как параллельно оценивает утверждение, подобное следующему:

(a) if ( ( a != null ) && ( a.equals(b) ) ) { ... }

приведет к сбою системы, архитектура, которая не имеет короткого замыкания (и, тем самым, не допускает таких утверждений, как указано выше) будет быстрее при обработке таких утверждений:

(b) if ( ( a == 4 ) && ( b == 5 ) )

поскольку, если он не может выполнить (a) параллельно, он не может выполнять (b) параллельно. В этом случае язык, который обеспечивает короткое замыкание, медленнее, чем тот, который этого не делает.

Я не знаю, верно это или нет.

Спасибо

Ответ 1

Булевые выражения с коротким замыканием в точности эквивалентны некоторому набору вложенных ifs, поэтому они эффективны, как это было бы.

Если b не имеет побочных эффектов, его можно выполнить параллельно с (для любого значения "параллельно", включая конвейерную обработку).

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

Но короткое замыкание используется для потока управления, а также для экономии ненужной работы. Он распространен среди языков, которые я использовал, например, идиома Perl:

open($filename) or die("couldn't open file");

идиома оболочки:

do_something || echo "that failed"

или идиома C/С++/Java/etc:

if ((obj != 0) && (obj->ready)) { do_something; } // not -> in Java of course.

Во всех этих случаях вам требуется короткое замыкание, так что RHS оценивается только в том случае, если LHS диктует, что это должно быть. В таких случаях нет смысла сравнивать производительность с альтернативным кодом, что неправильно!

Ответ 2

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

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

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

Ответ 3

Честно говоря, я бы не стал беспокоиться об этом. Тестирование булева очень быстро. Короткое замыкание становится интересным/полезным, когда второе выражение имеет побочные эффекты:

if ( ConfirmAction() && DestroyAllData() )
   Reboot();

... или зависит от первого теста:

if ( myDodgyVar != null && myDodgyVar.IsActive() )
   DoSomethingWith(myDodgyVar);

Ответ 4

Языки, поддерживающие короткое замыкание:

Ada, Eiffel, ALGOL 68, C1, С++, С#, Java, R, Erlang, Standard ML, Javascript, MATLAB, Lisp, Lua, Scheme, OCaml, Haskell, Pascal, Perl, Ruby, PHP, Python, Smalltalk, Visual Basic.NET.

Взято из Оценка короткого замыкания

Ответ 5

У VB.Net есть другой синтаксис в зависимости от того, хотите ли вы его закорачивать или нет. Из-за унаследованных причин поведение по умолчанию - не короткое замыкание. Синтаксис выглядит следующим образом

Некороткая цепь

IF A And B THEN
    ...
END IF

Короткая цепь

IF A AndAlso B THEN
    ...
END IF

Вы можете использовать Or/OrElse, если вы хотите закоротить инструкцию OR. Что действительно приятно в ситуациях, подобных следующим

If MyObj IsNot Nothing AndAlso MyObj.Value < SomeValue Then
    ....
End If

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

Ответ 6

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

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

Ответ 7

Как может вложенный, если не срыв? На самом деле, если a и b являются переменными, а не выражениями с побочными эффектами, они могут быть загружены параллельно хорошим компилятором. Нет никакой пользы от использования большего количества ifs, кроме увеличения количества строк. На самом деле это будет худший вариант второго угадывания компилятора.

Он назвал оценку короткого замыкания.

Ответ 8

Полезное короткое замыкание, которое я использую, выглядит примерно так:

if (a != null && a.equals(somevalue)) {
    ... do something.
}

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

Все мое мнение.

Ответ 9

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

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

В качестве примера, когда это было бы хорошо, представьте себе игровую программу, которая имеет что-то вроде:

if (someObject.isActive() && someOtherObject.isActive() && CollisionDetection.collides(someObject, someOtherObject) {
  doSomething();
}

В этом случае обнаружение столкновения намного дороже, чем активные проверки. Было бы значительное повышение производительности, если бы в системе было много неактивных объектов.

Ответ 10

В зависимости от контекста его также можно назвать "Охрана".

И я видел это практически на каждом языке, на котором я работал, - который приближается к дюжине.

Ответ 11

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

Ответ 12

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

Ответ 13

Короткое замыкание или минимальная оценка - это просто синтаксический сахар для вложенных ifs. Предполагать, что это неэффективно или вызывает киоски - это случай преждевременной оптимизации. На данный момент большинство компиляторов достаточно интеллектуальны, чтобы правильно интерпретировать и оптимизировать эти утверждения. Использование этих операторов может значительно уменьшить вложенность и, следовательно, улучшить читаемость кода, что должно стать вашей целью номер один.

Ответ 14

Один поток является последовательным, поэтому, если у вас есть два if, первый, конечно, будет оценен до второго, поэтому я не вижу различий в этом. Я использую оператор условного-И (который является тем, что && называется afaik) намного больше, чем вложенные ifs. Если я хочу проверить что-то, что может потребоваться некоторое время для оценки, я делаю более простой тест сначала, чем сложнее после условного и.

a = obj.somethingQuickToTest() && obj.somethingSlowToTest();

похоже, не отличается от

a = false;
if(obj.somethingQuickToTest())
   a = obj.somethingSlowToTest();

Ответ 15

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

Вложенные ifs будут иметь тот же эффект, что и short-circuiting &.

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