che sto funzionando in un comportamento ottimizzazione incoerente con differenti compilatori per il codice seguente:ottimizzazione di accesso ai membri in C++
class tester
{
public:
tester(int* arr_, int sz_)
: arr(arr_), sz(sz_)
{}
int doadd()
{
sm = 0;
for (int n = 0; n < 1000; ++n)
{
for (int i = 0; i < sz; ++i)
{
sm += arr[i];
}
}
return sm;
}
protected:
int* arr;
int sz;
int sm;
};
La funzione doadd
simula qualche accesso intensivo ai membri (ignorare i overflow in aggiunta per questa domanda). Rispetto al codice simile implementato come una funzione:
int arradd(int* arr, int sz)
{
int sm = 0;
for (int n = 0; n < 1000; ++n)
{
for (int i = 0; i < sz; ++i)
{
sm += arr[i];
}
}
return sm;
}
Il metodo doadd
corre circa 1,5 volte più lento rispetto alla funzionearradd
quando compilato in modalità di rilascio con Visual C++ 2008. Quando modifico il metodo doadd
essere il seguente (aliasing tutti i membri con i locali):
int doadd()
{
int mysm = 0;
int* myarr = arr;
int mysz = sz;
for (int n = 0; n < 1000; ++n)
{
for (int i = 0; i < mysz; ++i)
{
mysm += myarr[i];
}
}
sm = mysm;
return sm;
}
I runtime diventano più o meno gli stessi. Ho ragione nel concludere che questa è una ottimizzazione mancante dal compilatore Visual C++? g++
sembra farlo meglio ed eseguire sia la funzione membro che la funzione normale alla stessa velocità durante la compilazione con -O2
o -O3
.
L'analisi comparativa è fatto invocando la funzione doadd
membro e arradd
su alcuni sufficientemente grande matrice (alcuni milioni di numeri interi di dimensione).
EDIT: Alcuni test a grana fine mostra che il colpevole principale è il membro sm
. Sostituire tutti gli altri con le versioni locali rende ancora il runtime lungo, ma una volta che ho sostituito sm
da mysm
il runtime diventa uguale alla versione della funzione.
Risoluzione
deluso con le risposte (mi dispiace), ho Shaked fuori la mia pigrizia e colomba nelle liste di smontaggio di questo codice. Il mio answer below riassume i risultati. In breve: non ha nulla a che fare con l'aliasing, ha a che fare con lo srotolamento del ciclo e con alcune strane euristiche MSVC si applica quando si decide quale ciclo eseguire.
L'istanza di 'tester' è allocata nell'heap? – ereOn
Forse è a causa del caching? li hai chiamati in ordine diverso? – ruslik
@eeOn: no, nello stack in 'main' –