2015-07-24 25 views
12

In questo Stack Overflow answer è dimostrato che l'aliasing in C++ può rallentare il codice. E l'aliasing in C++ non si applica solo ai puntatori, si applica anche ai riferimenti e, più in generale, a these types specified by the standard. In particolare, v'èCome evitare l'aliasing e migliorare le prestazioni?

un tipo di aggregato o unione che include uno dei tipi indicati sopra tra i suoi componenti (compresi, ricorsivamente, un membro di un subaggregate o unione contenuta)

Quindi, secondo la mia comprensione , se ho codice come qui di seguito,

class A{ 
    public: 
    int val; 
}; 

void foo(vector<A> & array, int & size, A & a0) { 
    for(int i=0;i<size;++i) { 
    array[i].val = 2*a0.val; 
    } 
} 

ed è possibile che a0 può alias uno degli elementi in array, anche eventualmente alias size causa di la citazione di cui sopra, quindi a0 e size devono essere caricati per ogni iterazione con conseguente riduzione delle prestazioni.

  1. Quindi la mia domanda è cosa devo fare al codice per evitare l'aliasing e migliorare le prestazioni?
  2. Il passaggio da const & non aiuta poiché non eviterà l'aliasing come specificato dallo standard. Passa a0 in base al valore? Ma questo farà una copia di a0 che non mi piace, dal momento che in pratica la classe A può essere molto complessa e la copia è un'opzione molto costosa.
  3. Esiste una soluzione generale per evitare l'aliasing in C++? Se sì, che cos'è?
+0

La proposta che faccio riferimento a [Clark Nelson è pertinente] (http://stackoverflow.com/a/27914489/1708801) sebbene sia una proposta in C che menziona è rilevante anche per WG21 (C++) anche se lui non ha avuto il tempo di fornire la dicitura WG21. –

+0

Non ho molta familiarità con il comportamento di aliasing ma di quello che sto leggendo, purché i valori che la funzione ha bisogno di leggere possano essere provati dal compilatore per non essere potenziali alias l'uno dell'altro secondo le regole, dovrebbe evitare le spese generali di aggiornamento del valore ogni volta. Ad esempio, in questo esempio (e potrei sbagliarmi) non ci dovrebbe essere aliasing perché 'int',' vector 'e' A' non sono tipi che possono riferirsi tra loro ad eccezione di 'int &' puntando a 'A :: val'. –

+1

@XerenNarcy 'a0' potrebbe essere un riferimento a uno degli elementi di' array' –

risposta

6

La questione di evitare problema di prestazioni aliasing in C++ sembra essere coperto da Evolution Working Group issue 72: N4150 Alias-Set Attributes: Toward restrict-like aliasing semantics for C++, N3988 Towards restrict-like aliasing semantics for C++ N3635 Towards restrict-like semantics for C++ e N4150 era l'ultima versione della proposta. Il problema relativo all'EWG non è stato ancora risolto, ma a quanto pare è considerato pronto per la revisione.

La proposta propone di C come limitare le qualificazioni, che attualmente sono supportati da estensioni in C++ da molti compilatori, ma hanno zone sfocate, la proposta dice tra le altre cose:

Non c'è dubbio che la limitano i benefici di qualificazione compilatore ottimizzazione in molti modi, in particolare consentendo un miglioramento del codice di movimento e l'eliminazione di carichi e negozi . Dall'introduzione della limitazione C99 , è stato fornito come estensione C++ in molti compilatori. Ma la funzionalità è fragile in C++ senza regole chiare per la sintassi C++ e semantica. Ora con l'introduzione di C++ 11, i funtori sono sostituiti con lambdas e gli utenti hanno iniziato a chiedere come usare la limitazione in presenza di lambda. Dato il supporto del compilatore esistente, abbiamo necessario fornire una soluzione con semantica C++ ben definita, prima che l'utilizzo di alcuni sottoinsiemi comuni di C99 restino ampiamente utilizzato nella combinazione con i costrutti C++ 11 prima dello .

la proposta note anche:

Senza la standardizzazione e il miglioramento della C99 esistente limitare l'impianto in C++, gli utenti in genere hanno i salti notevoli mortali per ottenere il suo effetto attraverso codice riscrittura attraverso provvisori, o factoring e inlining corpi delle funzioni per simulare il suo effetto.

Così sembra che non esiste attualmente alcuna buona soluzione, anche se i compilatori attuali hanno estensioni che offrono C limitano come la semantica ci sono un sacco di grigio sezione aree 3. Problemi con limitano in C++ e C copre alcune delle i metodi usati per evitare l'aliasing ma hanno tutti difetti.

La proposta menzionava N3538 che menziona alcune delle tecniche e dei difetti associati a queste tecniche. Per esempio:

La tecnica più semplice per superare l'aliasing è quello di copiare il parametri potenzialmente aliasing.

void rf2(type& output, const type& input) { 
    type temp = input; 
    output += ra1(temp); 
    output += ra2(temp); 
} 

Questa tecnica è più complessa e meno efficiente che semplicemente passando il parametro per valore. Mentre la tecnica può essere utile quando si occupa di interfacce legacy, non dovrebbe essere una tecnica primaria.

Questa tecnica si applica al tuo caso.

Nota per interessante assumere aliasing e C99 limitatore qualificatore On the redundancy of C99's restrict.

+0

Grazie, ottima risposta. – Allanqunzi

1

Se l'intento è che non si aspettava size o a0.val di cambiare durante l'esecuzione di foo, allora si può fare che esplicita avendo questi siano valori locali:

void foo(vector<A> & array, int size, const A & a0) { 
    auto new_val = 2*a0.val; 
    for(int i=0;i<size;++i) { 
     array[i].val = new_val; 
    } 
} 

Ora è chiaro che si intendiamo impostare tutti gli elementi sullo stesso valore. È chiaro sia per il lettore che per il compilatore.

Problemi correlati