Pregunta

Tengo un extraño problema. He siguiente fragmento de código:

template<clss index, class policy>
inline int CBase<index,policy>::func(const A& test_in, int* srcPtr ,int* dstPtr)
{
    int width = test_in.width();
    int height = test_in.height();

    double d = 0.0; //here is the problem
    for(int y = 0; y < height; y++)
    {

        //Pointer initializations

        //multiplication involving y
        //ex: int z = someBigNumber*y + someOtherBigNumber;
        for(int x = 0; x < width; x++)
        {
            //multiplication involving x
        //ex: int z = someBigNumber*x + someOtherBigNumber;
            if(soemCondition)
            {
                // floating point calculations
            }
            *dstPtr++ = array[*srcPtr++];
        }
    }
}

El bucle interno es ejecutado cerca de 200.000 veces y la función entera toma 100 ms para su conclusión. (Perfilada usando AQTimer)

he encontrado un double d = 0.0; variable de no utilizado fuera del bucle exterior y se retira la misma. Después de este cambio, de repente, el método está llevando a 500 ms para el mismo número de ejecuciones. (5 veces más lento).

Este comportamiento es reproducible en diferentes máquinas con diferentes tipos de procesador. (Core2, procesadores DualCore).

Estoy utilizando el compilador VC6 con O2 nivel de optimización. Follwing son las otras opciones del compilador utilizado:

 -MD -O2 -Z7 -GR -GX -G5 -X -GF -EHa

Yo sospechaba optimizaciones del compilador y se retira el /O2 optimización del compilador. Después de que la función se normalizó y se toma como 100 ms viejo código.

¿Alguien podría arrojar alguna luz sobre este extraño comportamiento?

¿Por qué la optimización del compilador debe ralentizar el rendimiento cuando quito la variable no utilizada?

Nota: El código de montaje (antes y después del cambio) parecía misma

.

No hay solución correcta

Otros consejos

Si el código de montaje tiene el mismo aspecto antes y después del cambio el error está conectado de alguna manera a cómo se mide el tiempo de la función.

VC6 está libre de errores como el demonio. Es conocido para generar un código incorrecto en varios casos, y su optimizador no es todo lo que avanzó tampoco. El compilador es más de diez años, e incluso no ha sido apoyada por muchos años.

Así que en realidad, la respuesta es "que está utilizando un compilador buggy. Esperar un comportamiento con errores, sobre todo cuando se habilitan optimizaciones."

hago la actualización no suponga que un compilador moderno (o simplemente probar el código en uno) es una opción?

Obviamente, el ensamblado generado no puede ser el mismo, o no habría ninguna diferencia de rendimiento.

La única pregunta es donde las mentiras de diferencia. Y con un compilador de errores, que bien puede ser una parte totalmente sin relación del código que de repente se compila de manera diferente y se rompe. Lo más probable, sin embargo, el código ensamblador generado para esta función es no de la misma, y ??las diferencias son tan sutiles que no se dio cuenta de ellos.

width declarar y height como const {} sin firmar enteros. { La unsigned debe ser usado desde alturas y anchuras nunca son negativas. }

const int width = test_in.width();
const int height = test_in.height();

Esto ayuda a que el compilador con la optimización. Con los valores como const, puede colocarlos en el código o en los registros, sabiendo que no van a cambiar. Además, alivia el compilador de tener que adivinar si las variables están cambiando o no.

Sugiero imprimir el código de montaje de las versiones con la double sido utilizados y sin. Esto le dará una idea de proceso de pensamiento del compilador.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top