Pergunta

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

Na maioria das linguagens, b não vai ficar avaliada porque a é falso tão a && b não pode ser verdade. A minha pergunta é, curto-circuito não seria mais lento em termos de arquitetura? Em um oleoduto, você simplesmente parar enquanto espera para obter o resultado de um para determinar se b deve ser avaliada ou não? Seria melhor para fazer ifs aninhados em vez disso? Será que mesmo ajuda?

Além disso, alguém sabe o que curto-circuito avaliação é normalmente chamado? Esta questão surgiu depois que eu descobri que o meu amigo de programação nunca tinha ouvido falar de avaliação curto-circuito e declarou que não é comum, nem encontrado em muitos idiomas, e é ineficiente no pipeline. Não estou certo sobre o último, então pedir-lhe folks!

Ok, eu acho que um exemplo diferente, talvez, explicar onde meu amigo pode estar vindo. Ele acredita que, uma vez avaliando uma declaração como a seguinte em paralelo:

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

irá travar o sistema, uma arquitetura que não tem um curto-circuito (e, assim, não permitindo que declarações como as acima) seria mais rápido no processamento de declarações como estes:

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

pois se ele não poderia fazer (a) em paralelo, não pode fazer (b) em paralelo. Neste caso, uma linguagem que permite curto-circuito é mais lento do que um que não o faz.

Eu não sei se isso é verdade ou não.

Graças

Foi útil?

Solução

O curto-circuito expressões booleanas são exatamente equivalente a um conjunto de ifs aninhados, por isso são tão eficientes como isso seria.

Se b não tem efeitos colaterais, ele ainda pode ser executado em paralelo com um (para qualquer valor de "em paralelo", incluindo pipelining).

Se b tem efeitos colaterais que a arquitetura CPU não pode cancelar quando previsão de desvios falhar, então sim, isso pode exigir atrasos que não estaria lá se ambos os lados foram sempre avaliados. Por isso é algo para olhar se você encontrar sempre que os operadores-circuito curtas estão criando um gargalo de desempenho em seu código, mas não vale a pena se preocupar com o contrário.

Mas curto-circuito é usado para controle de fluxo, tanto quanto para salvar trabalho desnecessário. É comum entre as línguas que eu usei, por exemplo, a linguagem Perl:

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

o idioma shell:

do_something || echo "that failed"

ou a C / C ++ / Java / etc idioma:

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

Em todos esses casos, você precisa de um curto-circuito, de modo que o RHS é avaliada somente se os ditames LHS que deveria ser. Em tais casos, não há nenhum ponto comparando o desempenho com código alternativo que é! Errado

Outras dicas

Avaliação Curto-circuito é traduzido em ramos em linguagem assembly da mesma forma se as declarações são (ramos são basicamente um goto), o que significa que não vai ser mais lento do que se declarações.

Ramos não costumam parar o oleoduto, mas o processador irá adivinhar se o ramo é tomado ou não, e se o processador estiver errado, terá que lave tudo o que aconteceu desde que fez o palpite errado do pipeline.

Avaliação Curto-circuito é também o nome mais comum para isso, e é encontrado na maioria das linguagens de alguma forma ou de outra.

Eu honestamente não me preocuparia com isso. Testando um boolean é muito rápido . O curto-circuito só fica interessante / útil quando a segunda expressão tem efeitos colaterais:

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

... ou depende do primeiro teste:

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

Línguas apoiar curto-circuito:

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

avaliação curto-circuito

VB.Net tem uma sintaxe diferente, dependendo se deseja ou não que um curto-circuito ou não. Devido a razões de legado, o comportamento padrão é para o circuito não curto. A sintaxe é a seguinte

Circuit Não curto

IF A And B THEN
    ...
END IF

Curto-circuito

IF A AndAlso B THEN
    ...
END IF

Você pode usar Ou / OrElse se você quiser curto-circuito um OR comunicado. Que é muito bom em situações como a seguinte

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

Pessoalmente, enquanto eu entendo que curto-circuito pode acelerar as coisas, não é definitivamente algo que é óbvio de apenas olhando o código. Eu podia ver um desenvolvedor inexperiente ficar confuso com o comportamento. Ele ainda parece ser algo que poderia acontecer ou não, dependendo bandeiras do compilador para nível de otimização. Eu gosto de como VB é detalhado sobre qual comportamento que você realmente quer realizar.

Em primeiro lugar, o seu amigo está errado. avaliação de curto-circuito (aka avaliação mínima) está disponível na maioria dos idiomas e é melhor do que ifs aninhados para linguagens paralelas (no caso da primeira das condições que os retornos fará com que a execução continue qual)

Em qualquer caso, mesmo em uma linguagem não-paralela simples Eu não vejo como ifs aninhados seria mais rápido como a execução iria bloquear até que a primeira condição é avaliada.

Como pode um aninhados se não parar? Na verdade, se a e b são ambos variáveis ??e não expressões com efeitos colaterais, que pode ser carregado em paralelo por uma boa compilador. Não há nenhuma vantagem de se utilizar mais ifs, exceto aumentar sua contagem de linha. Realmente, este seria o pior tipo de adivinhar segundo um compilador.

É chamado de avaliação de curto-circuito.

A utilização útil circuito que eu curto é algo como isto:

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

Esta é, na minha opinião muito legível, e funciona muito bem. Geralmente, eu tento também evitar a muito nidificação, pois leva a código feio.

Toda a minha opinião embora.

A maioria das linguagens fazer avaliação de curto-circuito de expressões booleanas. Sempre ouvi-lo referido como avaliação de curto-circuito.

O exemplo em questão é um exemplo simplista bonita que realmente não fornecer muito de um benefício de desempenho. O benefício de desempenho vem quando as expressões são complexas para avaliar.

Como um exemplo de quando isso seria bom imaginar um programa de jogo que tem algo como:

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

Neste caso, a detecção de colisão é muito mais caro do que as verificações ativas. Haveria um ganho significativo de performance se havia muitos objetos inativos no sistema.

Curto-circuito ou avaliação mínima é apenas açúcar sintático para ifs aninhados. Para assumir que é ineficiente, ou faz com barracas é um caso de otimização prematura. Neste ponto, a maioria dos compiladores são suficientes inteligente para interpretar e otimizar essas declarações corretamente. Usando estas declarações podem reduzir muito nidificação, e, portanto, melhorar a legibilidade do código, que deve ser seu objetivo número um.

No que diz respeito ou não curto-circuito é eficiente, pipelining é improvável que tenha um impacto muito grande no desempenho. Em situações em que ele poderia ter um impacto, não há nada para parar o compilador de testar múltiplas condições em paralelo, desde que estes testes não tem efeitos colaterais. Além disso, CPUs modernas têm vários mecanismos úteis para melhorar o desempenho do pipeline de código branchy.

ifs aninhados terá o mesmo efeito que um curto-circuito &&.

'avaliação de curto-circuito' é o nome mais comum para ele, e seu amigo está errado sobre ele que é incomum; é muito comum.

Eu não sei nada sobre pipeline, mas a avaliação de curto-circuito é uma característica comum de muitas línguas (e que é também o nome eu sei que por). Em C, && e os outros operadores definir um href="http://en.wikipedia.org/wiki/Sequence_point" rel="nofollow noreferrer"> sequência ponto

Eu só ouvi falar dele como curto-circuito. em uma tubulação doesnt a próxima op que vai na depender do resultado da instrução if? se for esse o caso, esta seria mais otimizado para que ele não teria que teste de dois valores de cada vez.

Um único segmento é tão seqüencial se você tiver dois ifs o primeiro vai, naturalmente, ser avaliados antes do segundo, então eu não posso ver uma diferença nisso. Eu uso o condicional E operador (que é o que é chamado && afaik) muito mais do que ifs aninhados. Se eu quiser verificar algo que pode demorar um pouco para avaliar, eu faço o teste mais simples primeiro e depois o mais difícil, uma após a condicional e.

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

não parece ser diferente do que

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

Dependendo do contexto, pode também ser chamado de "Guarda".

E eu já vi isso em quase todas as línguas Eu trabalhei em -. Que empurra perto de uma dúzia

scroll top