2011-05-30 7 views
33

Tengo 2 funciones de kernel muy similares, en el sentido de que el código es casi el mismo, pero con una ligera diferencia. Actualmente tengo 2 opciones:¿Debo unificar dos kernels similares con una declaración 'if', arriesgando la pérdida de rendimiento?

  • Comentario 2 métodos diferentes (pero los muy similares)
  • escribir un solo núcleo y poner los bloques de código que difieren en una sentencia if/else

¿Cuánto ¿afectará una declaración if a mi rendimiento de algoritmo?
Sé que no hay bifurcación, ya que todos los hilos en todos los bloques entrarán en el if o el else.
Entonces, ¿una única instrucción if disminuirá mi rendimiento si se llama a la función kernel muchas veces?

+4

¿Por qué no probar ambos y tiempo? – Bart

Respuesta

91

Tiene una tercera alternativa, que es usar plantillas C++ y hacer que la variable que se utiliza en la sentencia if/switch sea un parámetro de plantilla. Crea una instancia de cada versión del kernel que necesites, y luego tienes varios kernels haciendo cosas diferentes sin divergencia de rama o evaluación condicional de la que preocuparte, porque el compilador optimizará el código muerto y la ramificación con él.

Tal vez algo como esto:

template<int action> 
__global__ void kernel() 
{ 
    switch(action) { 
     case 1: 
     // First code 
     break; 

     case 2: 
     // Second code 
     break; 
    } 
} 

template void kernel<1>(); 
template void kernel<2>(); 
+3

muy inteligente. Me gusta. –

+4

@talonmies ... Esta respuesta es la más útil que he visto en SO. La cantidad de granos CUDA en mi código se reduce aproximadamente 4 veces. :) – sgarizvi

+3

¡Esto hace que todos los códigos que he visto se vean feos! –

4

Se disminuirá ligeramente su rendimiento, especialmente si es en un bucle interno, ya que está perdiendo una ranura tema de instrucciones de vez en cuando, pero no es casi tanto como si un warp fuera divergente.

Si es un gran problema, puede valer la pena mover la condición fuera del circuito, sin embargo. Si la trama es realmente divergente, sin embargo, pensar acerca de cómo quitar la ramificación: por ejemplo, en lugar de

if (i>0) { 
    x = 3; 
} else { 
    x = y; 
} 

tratar

x = ((i>0)*3) | ((i<3)*y); 
Cuestiones relacionadas