2008-10-23 21 views
12

que recuerdo de C día que nos animaron a usarUso "mayor o igual" o simplemente "mayor que"

i > -1 

en lugar de

i >= 0 

causa de rendimiento.

¿Esto todavía se aplica en el mundo C# .NET? ¿Cuáles son las implicaciones de rendimiento de usar uno sobre el otro con los compiladores de hoy? Es decir, ¿es el compilador lo suficientemente inteligente como para optimizar estos para usted?

(Dicho sea de paso tratar de escribir la pregunta "uso> = o>" en el campo de interrogación en desbordamiento de pila y ver qué pasa.)

Respuesta

44

No, no hay problemas de rendimiento asociados con los operadores de comparación. Y cualquier buen compilador optimizaría algo así de trivial de todos modos.

No estoy seguro de dónde recibió la sugerencia de utilizar "i> -1" en lugar de "i> = 0". En la arquitectura x86, no hace ninguna diferencia que se utiliza: cualquiera de los casos tiene exactamente dos instrucciones ... uno para comparar y uno para saltar:

;; if (i > -1) { 
cmp eax, -1 
jle else 
then: 
... 
else: 

;; if (i >= 0) { 
cmp eax, 0 
jl else 
then: 
... 
else: 

en la mayoría de las arquitecturas RISC, que yo sepa, "i> = 0 "en realidad puede ser más rápido ya que generalmente hay un registro de cero dedicado, y" i> -1 "puede requerir cargar una constante. Por ejemplo, MIPS solo tiene una instrucción < (no < =). (! Ingenuamente) Aquí es cómo serían las dos construcciones expresaron en MIPS lenguaje ensamblador:

// if (i >= 0) { (assuming i is in register %t0) 

stl $t1, $0, $t0  // in C: t1 = (0 < t0) 
beq $t1, $0, else // jump if t1 == 0, that is if t0 >= 0 
nop 
then: 
... 
else: 

// if (i > -1) { (assuming i is in register %t0) 

addi $t2, $0, -1  // in C: t2 = -1 
stl $t1, $t2, $t0  // in C: t1 = (t2 < t0) = (-1 < t0) 
bne $t1, $0, else  // jump if t1 != 0, that is if t0 > -1 
nop 
then: 
... 
else: 

Así, en el caso ingenuo, en general, en realidad será una instrucción más rápida de hacer "i> = 0" en MIPS . Por supuesto, el código RISC es tan optimizable que un compilador probablemente cambiaría cualquiera de estas secuencias de instrucciones casi irreconocible :-)

Entonces ... la respuesta corta es no no no, no hay diferencia.

+5

'(no no no, ninguna diferencia) =! (! (! (! Diferencia))) =! (! Diferencia)) = diferencia';) –

+1

@ M.kazemAkhgary, difícil de discutir con ese. Ahora estoy un poco tentado de agregar un 5º "no" :-P –

5

No, no es necesario hacer esto nunca más. Sí, los compiladores se han vuelto mucho más inteligentes y las dos expresiones no tienen diferencias de rendimiento.

+0

Todavía no puedo creer que haya habido un entorno donde * haría * la diferencia. ¿Alguien puede decirme de una arquitectura existente donde uno requiere menos ciclos que el otro? –

+1

Suena como una leyenda urbana de programación –

3

Recuerdo de C días que nos animaron a usar ... por el rendimiento.

¿Estás seguro sobre eso? He trabajado con computadoras que datan de principios de los '70 (sí, a la altura de la rodilla de mi padre ...), y nunca vi una CPU que no pudiera procesar> = tan rápido como>. (BH "Branch High" vs. BNL "Branch Not Low" en IBM360 talk).

+0

Estoy de acuerdo, James. El que puedo pensar es MIPS, que solo tiene menos de. Por lo tanto, el compilador generalmente reorganiza "a <= b" a "no (b

+0

Creo que es un mito común. Lo he escuchado de compañeros de trabajo y lo he visto en Internet algunas veces, incluso en los últimos años. Incluso sin que el compilador optimice la diferencia, es una gran pérdida de esfuerzo guardar una instrucción de la CPU. – Mnebuerquo

+0

Como dices, probablemente fue algo de lo que me informaron mal, gracias. – Guy

9

Hay una pregunta muy similar (sin insinuar una crítica - como usted dice, la búsqueda de símbolos es complicado) aquí: "Should one use < or <= in a for loop"

(Sí, me resultan ser capaz de encontrarlo fácilmente como Tengo una muchas votaciones en mi respuesta ...)

Básicamente, haz lo que sea más legible.El día que alguien adivine correctamente que hacer un cambio lejos de la forma más legible resolverá un problema de rendimiento (sin la ayuda de un analizador) es el día en que dejo de hablar sobre el rendimiento :)

12

Además del hecho de que cualquier compilador decente hace lo correcto, y aparte del hecho de que en las arquitecturas modernas no hay diferencia de velocidad entre las comparaciones > y >=, la imagen más grande dice que se trata de una "micro-optimización" que no afecta el rendimiento del tiempo de ejecución en el vasto mayoría de los casos.

En el caso de las comparaciones por lo general no afecta a la legibilidad de cualquier manera que lo escribe, pero hay ocasiones en las que elegir uno sobre el otro límite es clara: por ejemplo,

if (length >= str.size()) 

frente

if (length > str.size() - 1) 

No sé usted, pero elegiría la opción 1 cualquier día. :-) En los casos que no afectan apreciablemente el rendimiento, como este, la opción más legible debería ganar.

+1

Derecho encendido. "La optimización temprana es la raíz de todo mal." (Donald Knuth) –

+0

Tenga en cuenta que si str.size() devuelve una cantidad sin firmar, las dos declaraciones anteriores no son equivalentes. En particular, la última declaración nunca evaluará verdadero si str.size() es cero.A veces hice uso de dicho código, aunque generalmente agrego un tipo de transmisión explícito a unsigned: si los tamaños son 'cortos', "if (length> (unsigned short) (str.size-1))" ayudaría a aclarar que el código esperaría comportamiento de envoltura. – supercat

2

Eso podría haber sido cierto para algunos lenguajes de scripts sombreados que se dividen en> = en 2 comparaciones, pero quienquiera que lo motivó a usar eso para C ... bueno ... probablemente debería esforzarse por olvidar todo lo que alguna vez te lo dije.

2

Esto me recuerda la recomendación de utilizar ++ i en lugar de i ++ (preincremento frente a incremento posterior) porque fue supuestamente una instrucción más rápida. (Olvidé donde originalmente leí sobre esto, pero probablemente era C/C++ Users 'Journal o Dr. Dobb's Journal, pero parece que no puedo encontrar una referencia web.)

Tengo serias dudas de que> o> = es más rápido o más lento; en su lugar escribe tu código para mayor claridad.

Como nota al margen, desarrollé una preferencia para el operador de preincremento (++ i) incluso si el motivo ahora está desactualizado.

+1

En C++, hay razones para preferir un incremento sobre el otro; creo que es el incremento previo recomendado. –

-1

Para mayor que cero, debe hacer dos comprobaciones. Comprueba si el bit negativo está desactivado y comprueba si el bit cero está desactivado.

Para mayor o igual a cero, solo tiene que verificar si el bit negativo está desactivado, porque no nos importa si el bit cero está activado o desactivado.

Cuestiones relacionadas