2009-05-26 30 views
21

estoy haciendo un poco de codificación, donde tengo que escribir este tipo de código:¿Qué es más rápido? Comparación o asignación?

if(array[i]==false) 
    array[i]=true; 

Me pregunto si se debe volver a escribir como

array[i]=true; 

Esto plantea la pregunta: son comparaciones más rápidas que las asignaciones?

¿Qué pasa con las diferencias de idioma a idioma? (contraste entre java & cpp, por ej.)

NOTA: He oído que "la optimización prematura es la raíz de todo mal". No creo que se aplique aquí :)

+1

a menos que esté escribiendo un programa para un sistema integrado con un procesador muy lento, entonces no necesita preocuparse. Incluso en ese punto sería reacio a optimizar a mano –

+0

¿Puede la matriz [i] ser otra cosa que un bool? si no, entonces la reescritura es correcta. –

+0

Sí, la matriz es una matriz booleana. – jrharshath

Respuesta

14

Bueno, como dices que estás seguro de que esto es importante, solo debes escribir un programa de prueba y medir para encontrar la diferencia.

La comparación puede ser más rápida si este código se ejecuta en múltiples variables asignadas en direcciones dispersas en la memoria. Con la comparación, solo leerá los datos de la memoria en el caché del procesador, y si no cambia el valor de la variable cuando el caché decide vaciar la línea, verá que la línea no se modificó y no es necesario volver a escribirla. a la memoria Esto puede acelerar la ejecución.

+1

De acuerdo, por otro lado, algunas arquitecturas también tienen una penalización por la bifurcación ... Sólo se puede encontrar una respuesta verdadera midiendo . O mirando el código ensamblador generado, para ver si cambia (creo que no). –

+0

+1 para "medida" –

+1

¿No hace caches hacer esto automáticamente? es decir, verificar si los datos que se escriben son los mismos que los datos que están allí. – Jules

26

Esto no es sólo premature optimization, esto es micro-optimization, que es una distracción irrelevante.

Suponiendo que su matriz es de tipo booleano, entonces su comparación es innecesaria, que es la única observación relevante.

+1

Acepto ... puede ser que sea bueno desde el punto de vista de la legibilidad, pero ciertamente no si el cambio se está realizando para 'mejorar' el rendimiento. – Naveen

+0

+1: No podría estar más de acuerdo –

+0

@cletus, si solo es ** una llamada **, es una microoptimización. Si se trata de ** un billón ** de llamadas, se trata de una macro-optimización. De todos modos, el hilo relacionado en http://stackoverflow.com/q/23228359/632951 – Pacerier

0

Realmente no esperaría que hubiera ningún tipo de diferencia de rendimiento notable para algo tan trivial como esto, así que seguramente se trata de lo que le da un código claro y más legible. Yo mi opinión que siempre asignaría verdadero.

+0

Tampoco esperaría una diferencia de rendimiento. Es una cuestión de conocer la mejor opción del POV de rendimiento. – jrharshath

0

podría dar a este un intento:

if(!array[i]) 
    array[i]=true; 

Pero realmente la única manera de saber con seguridad es al perfil, estoy seguro de casi cualquier compilador ver la comparación de falso como innecesario y optimizarlo a cabo .

+0

Si su compilador es bueno, esto producirá un código de máquina idéntico. – Jules

0

Todo depende del tipo de datos. Asignar booleanos es más rápido que compararlos primero. Pero eso puede no ser cierto para los tipos de datos basados ​​en valores más grandes.

14

Editar: Escribí un guión en PHP. Me he dado cuenta de que había un error evidente en lo que significa que el tiempo de ejecución mejor de los casos estaba siendo calculado incorrectamente (miedo de que nadie más se dio cuenta!)

mejor de los casos solo late cesión pura y simple, pero peor de los casos es una mucho peor que simple asignación. La asignación es probablemente la más rápida en términos de datos del mundo real.

Salida:

  • asignación en 0.0119960308075 segundo
  • peor comparación de casos en 0.0188510417938 segundo
  • mejor comparación de casos en 0.0116770267487 segundos

Código:

<?php 
$arr = array(); 

$mtime = explode(" ", microtime()); 
$starttime = $mtime[1] + $mtime[0]; 

reset_arr($arr); 

for ($i=0;$i<10000;$i++) 
    $arr[i] = true; 


$mtime = explode(" ", microtime()); 
$firsttime = $mtime[1] + $mtime[0]; 
$totaltime = ($firsttime - $starttime); 
echo "assignment in ".$totaltime." seconds<br />"; 

reset_arr($arr); 

for ($i=0;$i<10000;$i++) 
    if ($arr[i]) 
     $arr[i] = true; 

$mtime = explode(" ", microtime()); 
$secondtime = $mtime[1] + $mtime[0]; 
$totaltime = ($secondtime - $firsttime); 
echo "worst case comparison in ".$totaltime." seconds<br />"; 

reset_arr($arr); 

for ($i=0;$i<10000;$i++) 
    if (!$arr[i]) 
     $arr[i] = false; 

$mtime = explode(" ", microtime()); 
$thirdtime = $mtime[1] + $mtime[0]; 
$totaltime = ($thirdtime - $secondtime); 
echo "best case comparison in ".$totaltime." seconds<br />"; 

function reset_arr($arr) { 
    for ($i=0;$i<10000;$i++) 
     $arr[$i] = false; 
} 
+0

Eso es interesante: ¡la tarea es realmente más rápida! – jrharshath

+0

Anuncio por un margen significativo, también: 14 ms frente a 22 a 39 ms. ¡Eso es un factor de 2! – MSalters

0

Como otros han señalado, esto es micro-optimización.

(en la política o el periodismo, esto se conoce como mirarse el ombligo ;-)

es el programa lo suficientemente grande como para tener más de un par de capas de llamadas de función/método/subrutina?

Si es así, es probable que haya tenido algunas llamadas evitables, y esas pueden desperdiciar cientos de veces más que ineficiencias de bajo nivel.

Suponiendo que tiene removed those (que pocas personas), ejecute 10^9 veces debajo de un cronómetro y vea cuál es más rápido.

0

Si lo que desea es dar la vuelta a los valores, a continuación, hacer:

array[i] = !array[i]; 

rendimiento utilizando este es en realidad peor, sin embargo, ya que en lugar de sólo tener que hacer un solo cheque para un cierto valor falso a continuación, establecer, se verifica dos veces

Si declara una matriz de elemento de 1000000 de comparación de patrones verdadero, falso, verdadero y falso es más lenta. (var b =! b) esencialmente realiza una comprobación dos veces en vez de una vez

1

Depende del idioma. Sin embargo, el bucle a través de las matrices también puede ser costoso. Si la matriz está en memoria consecutiva, la más rápida es escribir 1 bit (255s) en toda la matriz con memcpy suponiendo que su lenguaje/compilador puede hacerlo.

Por lo tanto, realizar 0 lecturas-1 escribir en total, no leer/escribir la variable de bucle/variable de matriz (2 lecturas/2 escribe cada bucle) varias cientos de veces.

+0

o con 'memset' en lugar de' memcpy' ... – Edmund

0

¿Por qué incluso escribir la primera versión? ¿Cuál es el beneficio de verificar si algo es falso antes de establecerlo como verdadero? Si siempre va a establecerlo como verdadero, siempre configúrelo como verdadero.

Cuando tiene un cuello de botella de rendimiento que ha rastreado hasta establecer un único valor booleano innecesariamente, vuelva y hable con nosotros.

1

Creo que si las declaraciones de comparación y asignación son atómicas (es decir, una instrucción de procesador) y el ciclo se ejecuta n veces, entonces en el peor de los casos, la comparación requerirá n + 1 (comparando en cada iteración más la asignación) ejecuciones, mientras que asignar constantemente el bool requeriría n ejecuciones. Por lo tanto, el segundo es más eficiente.

0

Recuerdo en un libro sobre el lenguaje ensamblador que el autor afirmaba que si se debía evitar la condición, si era posible. Es mucho más lento si la condición es falsa y la ejecución tiene que saltar a otra línea, reduciendo considerablemente el rendimiento. Además, dado que los programas se ejecutan en código máquina, creo que "si" es más lento en cada idioma (compilado), a menos que su condición sea verdadera casi todo el tiempo.

Cuestiones relacionadas