2012-03-28 13 views
10

Cuando estoy abajo a exprimir la última gota de rendimiento de un núcleo, por lo general encuentran que la sustitución de los operadores lógicos (&& y ||) con operadores de bits (& y |) hace que el núcleo de un poco más rápido . Esto se observó al observar el resumen de tiempo del kernel en CUDA Visual Profiler.CUDA: ¿Por qué los operadores bit a bit son a veces más rápidos que los operadores lógicos?

Entonces, ¿por qué los operadores bit a bit son más rápidos que que los operadores lógicos en CUDA? Debo admitir que son no siempre más rápido, pero muchas veces lo son. Me pregunto qué magia puede dar esta aceleración.

Descargo de responsabilidad: Soy consciente de que los operadores lógicos de cortocircuito y bit a bit no lo hacen. Soy muy consciente de cómo estos operadores pueden ser mal utilizados, lo que da como resultado un código incorrecto. Utilizo este reemplazo con cuidado solo cuando la lógica resultante sigue siendo la misma, hay una aceleración y la aceleración así obtenida me importa :-)

+0

¡Gracias por un gran consejo de optimización! –

+0

Roger: ¡Me alegra ayudar! Me sorprendió cuando descubrí esto también :-) –

Respuesta

11

Los operadores lógicos a menudo dan como resultado ramas, particularmente cuando se deben observar las reglas de la evaluación de cortocircuitos. Para las CPU normales esto puede significar mal predicción de derivaciones y para CUDA puede significar divergencia de distorsión. Las operaciones a nivel de bit no requieren una evaluación de cortocircuito, por lo que el flujo de código es lineal (es decir, sin derivación).

+1

Además, para el operador lógico, un resultado distinto de cero debe establecerse en 1. –

+1

@Roger: verdadero, pero a menudo esto se puede optimizar, por ejemplo. si la expresión solo se usa como parte de un condicional, el resultado solo necesita establecerse en 1 si se está asignando a una variable. –

1

Las operaciones de bit a bit se pueden llevar a cabo en los registros a nivel de hardware. Las operaciones de registro son las más rápidas, esto es especialmente cierto cuando los datos pueden caber en el registro. Las operaciones lógicas implican una evaluación de expresión que puede no estar vinculada al registro. Normalmente, &, |, ^, >> ... son algunas de las operaciones más rápidas y se utilizan ampliamente en lógica de alto rendimiento.

6

A & & B:

if (!A) { 
    return 0; 
} 
if (!B) { 
    return 0; 
} 
return 1; 

A & B:

return A & B; 

Estos son la semántica teniendo en cuenta que la evaluación de A y B puede tener efectos secundarios (que pueden ser funciones que alteran el estado del sistema cuando se evalúa).

Hay muchas maneras en que el compilador puede optimizar el caso A && B, dependiendo de los tipos de A y B y el contexto.

Cuestiones relacionadas