Question

J'ai un problème étrange. Je suit morceau de code:

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++];
        }
    }
}

La boucle interne est exécuté près de 200 000 fois et la fonction entière prend 100 ms pour l'achèvement. (Profilé en utilisant AQTimer)

I a trouvé une double d = 0.0; variable inutilisée en dehors de la boucle externe et enlevé les mêmes. Après ce changement, tout à coup la méthode prend 500ms pour le même nombre d'exécutions. (5 fois plus lent).

Ce comportement est reproductible dans différentes machines avec différents types de processeurs. (Core2, processeurs Dual Core).

J'utilise le compilateur VC6 avec le niveau d'optimisation O2. Follwing sont les autres options du compilateur utilisé:

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

Je soupçonne les optimisations du compilateur et a retiré le /O2 d'optimisation du compilateur. Après cette fonction est devenue normale et il prend 100ms que l'ancien code.

Quelqu'un pourrait-il jeter un peu de lumière sur ce comportement étrange?

Pourquoi l'optimisation du compilateur devrait ralentir les performances lorsque je retire variable inutilisée?

Note: Le code de montage (avant et après le changement) avait l'air même

.

Pas de solution correcte

Autres conseils

Si le code assembleur semble le même avant et après le changement de l'erreur est en quelque sorte lié à la façon dont vous le temps de la fonction.

VC6 est buggé comme l'enfer. Il est connu pour générer du code incorrect dans plusieurs cas, et son optimiseur est pas du tout avancé non plus. Le compilateur est plus de dix ans, et n'a même pas été pris en charge depuis de nombreuses années.

Alors, vraiment, la réponse est « vous utilisez un compilateur buggy. Expect comportement bogué, en particulier lorsque les optimisations sont activées. »

Je ne supposais pas la mise à niveau d'un compilateur moderne (ou simplement tester le code sur un) est une option?

De toute évidence, l'ensemble généré ne peut pas être le même, ou il n'y aurait pas de différence de performance.

La seule question est les mensonges de différence. Et avec un compilateur buggy, il peut bien être une partie tout à fait sans rapport avec le code qui est soudainement compilé différemment et les pauses. Très probablement cependant, le code assembleur généré pour cette fonction est pas les mêmes, et les différences sont tellement subtile que vous ne les avez pas remarqué.

Declare width et height comme const {} non signés ints. { unsigned doivent être utilisés depuis des hauteurs et largeurs ne sont jamais négatifs. }

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

Cela aide le compilateur à optimiser. Avec les valeurs que const, il peut les placer dans le code ou dans les registres, sachant qu'ils ne changeront pas. , Il soulage également le compilateur d'avoir à deviner si les variables changent ou non.

Je suggère d'imprimer le code d'assemblage des versions avec le double inutilisé et sans. Cela vous donnera un aperçu du processus de pensée du compilateur.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top