2010-03-03 13 views
6

¿Cuál es, en promedio, más rápido - verifique el valor, si es necesario, asigne o simplemente asigne? O, en C++ términos:Leer luego escritura condicional frente a escribir

bool b; 
if(b) 
    b = false; 

o

b = false; 

Suponga que la condición si() es verdadera con 50% de probabilidad. La respuesta será, muy probablemente, altamente dependiente de la arquitectura; por favor, exprese sus consideraciones de bajo nivel. Escribir siempre ensucia la línea de caché, ¿verdad? Así que al evitar una escritura evitamos un enjuague de caché en 0.5 casos. Pero una memoria caché lo suficientemente inteligente podría detectar una escritura trivial y no ensuciarse. Pero la escritura incondicional siempre es exactamente una operación de memoria, y la lectura-escritura es, en promedio, 1.5 operaciones.

Descargo de responsabilidad: esta es una pregunta de curiosidad, no es un problema que realmente enfrente.

+0

¿Importa lógicamente qué b es si el resultado final es que b debería ser falso? –

+0

@Fuzzy: se trata de optimización, no de lógica. –

+0

sí, pero el segundo es más fácil de leer y dice lo que hace, en mi opinión. – Earlz

Respuesta

4

Las ramificaciones son caras en las CPU modernas y el acceso a la memoria es costoso en las CPU integradas/antiguas. Así el justo-asignar plana siempre será más rápido a menos que tenga algo de memoria un poco raro que toma más tiempo para escribir que leer (pista: no lo hace)

es peor por estas razones en particular:

  • Una instrucción de ramificación. Esto puede ser predicho por el procesador, pero aún incurre en una posibilidad de sobrecarga.
  • 2 accesos a la memoria en lugar de 1. La lectura y escritura en la mayoría de las formas de memoria tienen la misma velocidad, entonces ¿por qué hacerlo dos veces cuando puede hacerlo una vez?
  • Más código adicional. este es un micro, pero se deben emitir más instrucciones para hacer la declaración if.Por lo tanto, significa un par adicional de lecturas de memoria y más espacio innecesariamente consumido en la memoria caché.
  • Y para el pesimista, podría significar que el compilador de C++ decide poner esta variable en un registro en lugar de otras variables necesarias más ..
  • Además, si se asume que b se pone en un registro. Registro lecturas/escrituras son muy baratos, pero no son libres ..
+0

Buen punto acerca de la predicción de ramificación (mis); ¿todavía se aplica a las CPU ARM donde if() 's se implementan sin ninguna bifurcación? –

+0

Todavía sería apenas más lento debido a la lectura extra de la memoria ... Incluso si tiene alguna instrucción mágica 'read-and-set-false-if-true', el procesador aún debe leer el valor de la memoria para probar si es verdad ... Y para la bifurcación en ARM, no, las fallas de la sucursal no se aplican realmente a la asignación condicional. en x86 'ccmov' no tiene una rama que no creo .. – Earlz

+0

Así que la gran decepción de R-W - error de predicción de ramas - no se aplica en ARM. La gran desventaja de W - cache flush - todavía lo hace, ¿no? –

1

Definitivamente valdría la pena perfilar esto en diferentes arquitecturas para obtener resultados reales.

1

Depende de varias cosas:

  • forma predecible la rama es (en el primer escenario)
  • si b es ya en un registro
  • lo que la arquitectura está utilizando
1

Además de las sugerencias para el perfil, también depende realmente de la memoria que respalda esa solicitud de escritura: si se trata de un dispositivo flash mapeado en memoria, por ejemplo, la escritura puede ser extremadamente costosa.

0

Si está haciendo una asignación de puntero, referencia o valor básico tipo I personalmente creo que la asignación directa será más rápida (entusiasta de ver el resultado en el generador de perfiles). En un entorno de probabilidad del 50%, es probable que ejecutes muchas más instrucciones para poner en valor el registro. Asignar objeto de estructura o clase que el operador de asignación de disparo será el más caro. La lógica condicional también introduce más instrucciones y se agrega a las métricas de complejidad del código

1

Recientemente he estado leyendo artículos sobre técnicas de compresión muy rápidas y muchachos insistieron en la necesidad de evitar la derivación if para lograr el mejor rendimiento. La razón de esto es la canalización de CPU. El uso de if s interrumpe muchas de las optimizaciones que una CPU puede realizar para ejecutar partes de código en paralelo. Entonces, si tenía muchas de estas operaciones, podría ser más rápido usar b = false.

1

En un procesador segmentado modernos que se necesitan para tener esto en cuenta:

  • cuesta una rama mispredicted mucho
  • las tiendas y las cargas tardan mucho tiempo
  • cachés pueden acelerar las lecturas y escrituras, pero si se trata de una arquitectura de varias caché y b se está modificando en más de una caché, varias escrituras pueden significar múltiples desalojos de caché y pueden compensar el rendimiento de la memoria caché

Leer con escritura condicional tiene al menos acceso a una memoria y una rama que pueden mispredict. Asumiendo que la rama se toma el 50% del tiempo, usted tiene 1.5 accesos de memoria en promedio, más la posibilidad de error de predicción.

La escritura incondicional tiene exactamente un acceso de memoria y ninguna rama en absoluto.

Ahora necesita equilibrar el costo de la predicción errónea con el costo de una tienda, que cambia según la cantidad de agentes de caché que tenga.

+0

¡Buen cálculo! – pajton

Cuestiones relacionadas