2012-03-03 15 views
5
// if I know that in_x will never be bigger than Max 
template <unsigned Max> 
void foo(unsigned in_x) 
{ 
    unsigned cap = Max; 

    // I can tell the compiler this loop will never run more than log(Max) times 
    for (; cap != 0 && in_x != 0; cap >>= 1, in_x >>= 1) 
    { 
    } 
} 

Como se muestra en el código anterior, mi conjetura es que si sólo escriboCómo dar el compilador de la pista sobre el tiempo máximo de un bucle correría

para (; in_x = 0;! In_x> > = 1)

el compilador no desenrollará el bucle, ya que no puede estar seguro del máximo posible en_x.

Deseo saber si estoy en lo cierto o no, y si hay algunas formas mejores de manejar estas cosas.


O tal vez el problema se puede generalizar como si uno puede escribir algo de código para indicar al compilador el rango de un valor de tiempo de ejecución, y tal código no es necesariamente ser compilado en el binario en tiempo de ejecución.


En verdad, la lucha con el compilador XD

// with MSC 
// if no __forceinline here, unrolling is ok, but the function will not be inlined 
// if I add __forceinline here, lol, the entire loop is unrolled (or should I say the tree is expanded)... 
// compiler freezes when Max is something like 1024 
template <int Max> 
__forceinline void find(int **in_a, int in_size, int in_key) 
{ 
    if (in_size == 0) 
    { 
     return; 
    } 

    if (Max == 0) 
    { 
     return; 
    } 

    { 
     int m = in_size/2; 

     if ((*in_a)[m] >= in_key) 
     { 
      find<Max/2>(in_a, m, in_key); 
     } 
     else 
     { 
      *in_a = *in_a + m + 1; 

      find<Max - Max/2 - 1>(in_a, in_size - (m + 1), in_key); 
     } 
    } 
} 
+8

Este tipo de cosas de micro-optimización tienden a ser impredecibles cuando se pelea con el compilador. Casi siempre termino desenrollando manualmente, pero nunca he intentado evitar que el compilador se desenrolle automáticamente. – Mysticial

+0

Incluso si un compilador conoce 'Max' y calcula' log (Max) ', suponga que ese valor es lo suficientemente grande como para que desenrollarlo sea una mala idea. Bueno, uno puede argumentar que tal vez el compilador podría usar un umbral. Pero ese umbral podría depender del ciclo específico. La predicción de rendimiento es un problema de compilación difícil. – Jerry

+0

@Jerry log (Max) será <= 32 (sin signo, no tan grande). –

Respuesta

3

La forma correcta de lograr este tipo de comportamiento es a rollo de la ONU el bucle de sí mismo utilizando TMP. Incluso con esto, dependerá de la cooperación del compilador para la creación masiva (que es no concedida). Eche un vistazo al siguiente código para ver si ayuda:

template <unsigned char MaxRec> 
inline void foo(unsigned in_x) 
{ 
    if (MaxRec == 0) // will be eliminated at compile time 
     return; // tells the compiler to stop the pseudo recursion 

    if (in_x == 0) { 
     // TODO : end recursion; 
     return; 
    }; 

    // TODO: Process for iteration rec 

    // Note: NOT recursion, the compiler would not be able to inline 
    foo<MaxRec-1>(in_x >> 1); 
} 

// Usage: 
foo<5>(in_x); // doubt the compiler will inline 32 times, but you can try. 
+1

MSC desenrollará una búsqueda binaria con una profundidad por debajo de 5 de esta manera, sin forzar la mayoría de los foo externos ... Si está forzado, alineará ambas ramas en lugar de desenrollar el bucle. – BlueWanderer

Cuestiones relacionadas