Domanda

Ho un problema sconosciuto. Ho seguente pezzo di codice:

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

Il ciclo interno viene eseguito quasi 200.000 volte e l'intera funzione prende 100 ms per il completamento. (Profilato utilizzando AQTimer)

ho trovato una double d = 0.0; variabile inutilizzata fuori l'anello esterno e l'estrazione dello stesso. Dopo questa modifica, improvvisamente il metodo sta prendendo 500ms per lo stesso numero di esecuzioni. (5 volte più lento).

Questo comportamento è riproducibile in diverse macchine con diversi tipi di processori. (Core2, processori DualCore).

Sto usando il compilatore VC6 con livello di ottimizzazione O2. Follwing sono le altre opzioni del compilatore utilizzate:

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

I sospettato ottimizzazioni del compilatore e rimosso il /O2 ottimizzazione del compilatore. Dopo che la funzione è diventato normale e sta prendendo 100ms come vecchio codice.

Qualcuno potrebbe gettare un po 'di luce su questo strano comportamento?

Perché l'ottimizzazione compilatore dovrebbe rallentare le prestazioni quando rimuovo variabile inutilizzati?

Nota: Il codice assembly (prima e dopo la modifica) sembrava stesso

.

Nessuna soluzione corretta

Altri suggerimenti

Se il codice assembly sembra la stessa, prima e dopo la modifica l'errore è in qualche modo collegato a come avete tempo la funzione.

VC6 è bacato come l'inferno. E 'noto per generare il codice errato in diversi casi, e il suo ottimizzatore non è poi così avanzato sia. Il compilatore è più di un decennio vecchio, e non è nemmeno stato sostenuto per molti anni.

Quindi, in realtà, la risposta è "si sta utilizzando un compilatore buggy. Aspettatevi comportamento buggy, soprattutto quando le ottimizzazioni sono abilitati."

Lo faccio l'aggiornamento non supponiamo di un compilatore moderno (o semplicemente testare il codice su uno) è un'opzione?

Ovviamente, il complesso generato non possono essere uguali, o non vi sarebbe alcuna differenza di prestazioni.

L'unica domanda è , dove le bugie di differenza. E con un compilatore buggy, può ben essere una parte completamente indipendenti del codice che improvvisamente viene compilato in modo diverso e si rompe. Molto probabilmente, però, il codice assembly generato per questa funzione è non lo stesso, e le differenze sono così sottili che non li hai notato.

Declare width e height come const {unsigned int}. { Il unsigned dovrebbe essere utilizzato in quanto altezze e larghezze sono mai negativi. }

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

Questo aiuta il compilatore con l'ottimizzazione. Con i valori come const, può metterli in codice o nei registri, sapendo che non cambieranno. Inoltre, allevia il compilatore di dover indovinare se le variabili stanno cambiando o meno.

Suggerisco di stampare il codice montaggio delle versioni con il double inutilizzato e senza. Questo vi darà una panoramica processo di pensiero del compilatore.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top