Pregunta

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

En la mayoría de los idiomas, b no será evaluado porque a es falso entonces a && b No puede ser cierto.Mi pregunta es: ¿no sería más lento el cortocircuito en términos de arquitectura?En una tubería, ¿se detiene mientras espera obtener el resultado de a para determinar si b debe evaluarse o no?¿Sería mejor hacer if anidados?¿Eso ayuda siquiera?

Además, ¿alguien sabe cómo se llama normalmente la evaluación de cortocircuito?Esta pregunta surgió después de que descubrí que mi amigo programador nunca había oído hablar de la evaluación de cortocircuitos y afirmó que no es común, ni se encuentra en muchos lenguajes, y que es ineficiente en la canalización.No estoy seguro del último, ¡así que les pregunto a ustedes!

Bien, creo que un ejemplo diferente quizás explique de dónde viene mi amigo.Considera que desde evaluar en paralelo una afirmación como la siguiente:

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

colapsará el sistema, una arquitectura que no tenga cortocircuitos (y por lo tanto no permita declaraciones como las anteriores) sería más rápida en el procesamiento de declaraciones como estas:

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

ya que si no pudo hacer (a) en paralelo, no puede hacer (b) en paralelo.En este caso, un lenguaje que permite cortocircuitos es más lento que otro que no lo permite.

No sé si eso es cierto o no.

Gracias

¿Fue útil?

Solución

Las expresiones booleanas de cortocircuito son exactamente equivalentes a algún conjunto de condiciones anidadas, por lo que son tan eficientes como sería.

Si b no tiene efectos secundarios, aún se puede ejecutar en paralelo con a (para cualquier valor de "en paralelo", incluida la canalización).

Si b tiene efectos secundarios que la arquitectura de la CPU no puede cancelar cuando falla la predicción de rama, entonces sí, esto podría requerir retrasos que no existirían si ambos lados siempre fueran evaluados.Por lo tanto, es algo que debe tener en cuenta si alguna vez descubre que los operadores de cortocircuito están creando un cuello de botella en el rendimiento de su código, pero de lo contrario no vale la pena preocuparse.

Pero el cortocircuito se utiliza tanto para controlar el flujo como para ahorrar trabajo innecesario.Es común entre los lenguajes que he usado, por ejemplo el modismo Perl:

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

el modismo de la concha:

do_something || echo "that failed"

o el modismo C/C++/Java/etc:

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

En todos estos casos es necesario un cortocircuito, de modo que el RHS solo se evalúe si el LHS así lo dicta.En tales casos, ¡no tiene sentido comparar el rendimiento con un código alternativo incorrecto!

Otros consejos

La evaluación de cortocircuito se traduce a ramas en lenguaje ensamblador de la misma manera que las declaraciones if (las ramas son básicamente un goto), lo que significa que no será más lenta que las declaraciones if.

Las bifurcaciones normalmente no detienen la tubería, pero el procesador adivinará si la rama se toma o no, y si el procesador se equivoca, tendrá que eliminar todo lo que sucedió desde que hizo una suposición incorrecta de la tubería.

La evaluación de cortocircuito también es el nombre más común y se encuentra en la mayoría de los idiomas de una forma u otra.

Sinceramente no me preocuparía por eso.Probar un booleano es realmente rápido.El cortocircuito sólo se vuelve interesante/útil cuando la segunda expresión tiene efectos secundarios:

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

...o depende de la primera prueba:

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

Idiomas que soportan cortocircuitos:

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 .NETO

Tomado de Evaluación de cortocircuito

VB.Net tiene una sintaxis diferente dependiendo de si desea que se produzca un cortocircuito o no.Por motivos heredados, el comportamiento predeterminado es no provocar un cortocircuito.La sintaxis es la siguiente.

Sin cortocircuito

IF A And B THEN
    ...
END IF

Cortocircuito

IF A AndAlso B THEN
    ...
END IF

Puede utilizar Or / OrElse si desea cortocircuitar una declaración OR.Lo cual es realmente agradable en situaciones como las siguientes.

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

Personalmente, aunque entiendo que los cortocircuitos pueden acelerar las cosas, definitivamente no es algo que sea obvio con solo mirar el código.Pude ver a un desarrollador sin experiencia confundido por el comportamiento.Incluso parece algo que podría suceder o no dependiendo de los indicadores del compilador para el nivel de optimización.Me gusta cómo VB es detallado sobre qué comportamiento realmente desea lograr.

Primero, tu amigo está equivocado.La evaluación de cortocircuito (también conocida como evaluación mínima) está disponible en la mayoría de los lenguajes y es mejor que los if anidados para lenguajes paralelos (en cuyo caso la primera de las condiciones que regrese hará que la ejecución continúe)

En cualquier caso, incluso en un lenguaje sencillo y no paralelo, no veo cómo los if anidados serían más rápidos ya que la ejecución se bloquearía hasta que se evalúe la primera condición.

¿Cómo puede un anidado si no detenerse?En realidad, si a y b son variables y no expresiones con efectos secundarios, un buen compilador puede cargarlas en paralelo.No hay ningún beneficio en usar más if excepto aumentar el número de líneas.Realmente, este sería el peor tipo de duda para un compilador.

Se llama evaluación de cortocircuito.

Un cortocircuito útil que uso es algo como este:

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

En mi opinión, esto es muy legible y funciona bastante bien.Generalmente, trato de evitar demasiado anidamiento porque genera código feo.

Aunque toda mi opinión.

La mayoría de los lenguajes realizan evaluaciones de cortocircuito de expresiones booleanas.Siempre he oído hablar de ello como evaluación de cortocircuito.

El ejemplo de la pregunta es bastante simplista y en realidad no proporciona muchos beneficios de rendimiento.El beneficio de rendimiento se produce cuando las expresiones son complejas de evaluar.

Como ejemplo de cuándo esto sería bueno, imagina un programa de juego que tenga algo como:

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

En este caso, la detección de colisiones es mucho más cara que los controles activos.Habría un aumento significativo del rendimiento si hubiera muchos objetos inactivos en el sistema.

El cortocircuito o la evaluación mínima es solo azúcar sintáctico para los if anidados.Asumir que es ineficiente o causa bloqueos es un caso de optimización prematura.En este punto, la mayoría de los compiladores son lo suficientemente inteligentes como para interpretar y optimizar correctamente estas declaraciones.El uso de estas declaraciones puede reducir en gran medida el anidamiento y, por lo tanto, mejorar la legibilidad del código, que debería ser su objetivo número uno.

En cuanto a si el cortocircuito es eficiente o no, es poco probable que la canalización tenga un gran impacto en el rendimiento.En situaciones en las que podría tener un impacto, no hay nada que impida que el compilador pruebe múltiples condiciones en paralelo, siempre y cuando estas pruebas no tengan efectos secundarios.Además, las CPU modernas tienen varios mecanismos útiles para mejorar el rendimiento de la canalización del código ramificado.

Los if anidados tendrán el mismo efecto que el cortocircuito &&.

'Evaluación de cortocircuito' es el nombre más común y tu amigo se equivoca al decir que es poco común;es muy común.

No sé nada sobre canalización, pero la evaluación de cortocircuito es una característica común de muchos lenguajes (y ese es también el nombre por el que la conozco).En C, && y los demás operadores definen un punto de secuencia al igual que el ;El operador lo hace, por lo que no veo cómo la evaluación de cortocircuito sea menos eficiente que simplemente usar múltiples declaraciones.

Sólo he oído hablar de ello como cortocircuito.en una tubería, ¿la siguiente operación no depende del resultado de la declaración if?Si ese es el caso, esto estaría más optimizado, por lo que no tendría que probar dos valores cada vez.

Un solo hilo es secuencial, por lo que si tiene dos if, el primero, por supuesto, se evaluará antes que el segundo, por lo que no veo ninguna diferencia al respecto.Utilizo el operador AND condicional (que es lo que afaik se llama &&) mucho más que los if anidados.Si quiero verificar algo que puede tardar un poco en evaluarse, primero hago la prueba más simple y luego la más difícil después del condicional y.

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

no parece ser diferente a

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

Dependiendo del contexto, también se le puede llamar "Guardar".

Y lo he visto en casi todos los idiomas en los que he trabajado, lo que supone cerca de una docena.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top