performance optimization refactoring

performance - ¿Cual es mas rápido? ¿Comparación o asignación?



optimization refactoring (12)

Estoy haciendo un poco de codificación, donde tengo que escribir este tipo de código:

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

Me pregunto si debería reescribirse como

array[i]=true;

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

¿Qué hay de las diferencias de un idioma a otro? (contraste entre java y cpp, por ejemplo)

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


¿Por qué incluso escribirías la primera versión? ¿Cuál es el beneficio de verificar si algo es falso antes de establecerlo? Si siempre lo va a establecer como verdadero, entonces hágalo siempre verdadero.

Cuando tiene un cuello de botella en el rendimiento que se remonta a la configuración de un solo valor booleano innecesariamente, vuelva y hable con nosotros.


Bueno, ya que dice que está seguro de que esto es importante, solo debe 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 a la memoria caché del procesador, y si no cambia el valor de la variable cuando la memoria caché decide vaciar la línea, verá que la línea no se cambió y no hay necesidad de volver a escribirla. a la memoria. Esto puede acelerar la ejecución.


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

(En política o periodismo, esto se conoce como mirar 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 algunas llamadas evitables, y esas pueden perder cientos de tiempo tanto como ineficiencias de bajo nivel.

En el supuesto de que haya eliminado esos (lo que pocas personas hacen), entonces, por supuesto, ejecútelo 10 ^ 9 veces bajo un cronómetro, y vea cuál es más rápido.


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


Depende del idioma. Sin embargo, el bucle a través de matrices también puede ser costoso. Si la matriz está en la memoria consecutiva, lo más rápido es escribir 1 bits (255s) en toda la matriz con memcpy, asumiendo que su idioma / compilador puede hacer esto.

De este modo, realizar 0 lecturas-1 total de escritura, sin leer / escribir la variable de bucle / variable de matriz (2 lecturas / 2 escribe cada bucle) varios cientos de veces.


Edit: escribí un script en PHP. Acabo de darme cuenta de que había un error evidente en el sentido de que el tiempo de ejecución del mejor caso se estaba calculando incorrectamente (¡da miedo que nadie más lo haya notado!)

El mejor de los casos simplemente supera la asignación directa, pero el peor de los casos es mucho peor que la simple asignación. La asignación es probablemente más rápida en términos de datos del mundo real.

Salida:

  • asignación en 0.0119960308075 segundos
  • La peor comparación de casos en 0.0188510417938 segundos
  • La 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; }


Esto no es solo una optimización prematura , 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.


Podría darle una oportunidad a esto:

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

Pero realmente la única forma de saberlo con seguridad es hacer un perfil, estoy seguro de que cualquier compilador vería la comparación como falsa como innecesaria y la optimizaría.


Realmente no esperaría que hubiera una diferencia notable en el rendimiento de algo tan trivial como este, así que seguramente se reduce a lo que le da un código claro y más legible. Yo opino que eso siempre sería asignar la verdad.


Recuerdo que, en un libro sobre lenguaje ensamblador, el autor afirmó que, si era posible, debía evitarse la condición. Es mucho más lento si la condición es falsa y la ejecución tiene que saltar a otra línea, lo que ralentiza considerablemente el rendimiento. Además, como los programas se ejecutan en código de máquina, creo que ''if'' es más lento en todos los lenguajes (compilados), a menos que su condición sea verdadera casi todo el tiempo.


Si solo quieres cambiar los valores, entonces haz:

array[i] = !array[i];

Sin embargo, el rendimiento de esto es realmente peor, ya que en lugar de tener que realizar solo una comprobación de un verdadero valor falso que se establece, se verifica dos veces.

Si declara una matriz de elementos 1000000 de verdadero, falso, verdadero, la comparación de patrones falsos es más lenta. (var b =! b) esencialmente hace un cheque dos veces en lugar de una vez


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