Compilatore di ottimizzazione che causa la prestazione di rallentare
-
02-10-2019 - |
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.