Преимущества использования оценки короткого замыкания - PullRequest
10 голосов
/ 18 сентября 2008
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) параллельно. В этом случае язык, который допускает короткое замыкание, медленнее, чем язык, который этого не делает.

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

Спасибо

Ответы [ 15 ]

12 голосов
/ 18 сентября 2008

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

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

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

9 голосов
/ 18 сентября 2008

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

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

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

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

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

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

do_something || echo "that failed"

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

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

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

8 голосов
/ 18 сентября 2008

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

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

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

if ( myDodgyVar != null && myDodgyVar.IsActive() )
   DoSomethingWith(myDodgyVar);
5 голосов
/ 21 июня 2009

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

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

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

3 голосов
/ 18 сентября 2008

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 многословен о том, какое поведение вы на самом деле хотите достичь.

2 голосов
/ 18 сентября 2008

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

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

1 голос
/ 18 сентября 2008

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

Вложенные if будут иметь тот же эффект, что и короткое замыкание &&.

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

1 голос
/ 18 сентября 2008

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

1 голос
/ 18 сентября 2008

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

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

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

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

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

1 голос
/ 18 сентября 2008

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

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

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

Хотя все мое мнение.

...