2012-05-04 13 views
5

Se utilizzo auto_ptr come valore di ritorno di una funzione che popola vettori di grandi dimensioni, questo rende la funzione una funzione di origine (creerà un auto_ptr interno e passerà sopra la proprietà quando restituisce un non const auto_ptr). Tuttavia, non posso usare questa funzione con gli algoritmi STL perché, per accedere ai dati, devo derefferenziare l'auto_ptr. Un buon esempio suppongo che sarebbe un campo di vettori di dimensione N, con ogni vettore con 100 componenti. Se la funzione restituisce ogni vettore di 100 componenti per valore o per ref non è la stessa, se N è grande.valore di ritorno ottimizzazione vs auto_ptr per vettori di grandi dimensioni

Inoltre, quando provo questo codice molto semplice:

class t 
{ 
    public: 
     t() { std::cout << "ctor" << std::endl; } 
     ~t() { std::cout << "dtor" << std::endl; } 
}; 

t valueFun() 
{ 
    return t(); 
} 

std::auto_ptr<t> autoFun() 
{ 
    return std::auto_ptr(new t()); 
} 

sia autoFun e chiamate divertenti risultato con l'uscita

CTOR dtor

quindi non posso effettivamente vedere la variabile automatico che è stato creato per essere passato alla dichiarazione di ritorno. Significa che l'ottimizzazione del valore di ritorno è impostata per la chiamata valueFun? ValueFun crea due oggetti automatici in questo caso?

Come è possibile ottimizzare una popolazione di una struttura di dati così grande con una funzione?

+0

Stai chiedendo se RVO funzionerà anche per i tuoi vettori di grandi dimensioni? Se è così, non puoi semplicemente testarlo con un esempio come quello sopra? – juanchopanza

+0

Quando lo collaudo, significa che funziona per tutti i compilatori/piattaforme? Come faccio a sapere che l'RVO è incluso, dovrei leggere le specifiche del compilatore? Cosa succede se il codice è compilato su un cluster HPC con un compilatore diverso e la libreria è grande? – tmaric

+0

Sì, capisco il tuo punto. È una di quelle cose che il compilatore è permesso, ma non è obbligato a fare, quindi non si può mai essere sicuri. BTW hai il supporto per C++ 11? – juanchopanza

risposta

4

ci sono molti opzioni per questo, e l'allocazione dinamica potrebbe non essere la migliore


Prima di addentrarci in questa discussione: si tratta di un collo di bottiglia?

Se non hai profilato e assicurato che si trattasse di un collo di bottiglia, questa discussione potrebbe essere completamente disattivata ... Ricorda che la creazione di profili di debug è praticamente inutile.


Ora, in C++ 03 ci sono diverse opzioni, dai più appetibile al minimo:

  • fiducia il compilatore: variabili senza nome utilizzano RVO anche nelle build di debug in gcc, per esempio.
  • utilizzare un parametro "out" (passaggio per riferimento)
  • allocare sul mucchio e restituire un puntatore (intelligente o no)
  • controllo del output del compilatore

Personalmente, mi affiderei la mia compilatore su questo a meno che un profiler non dimostri che ho torto.

In C++ 11, spostare la semantica ci aiuta a diventare più sicuri, perché ogni volta che c'è un'istruzione return, se RVO non può entrare, allora un costruttore di mosse (se disponibile) può essere usato automaticamente; e spostare i costruttori su vector sono sporchi a buon mercato.

Così diventa:

  • fiducia il compilatore: la semantica o RVO o spostare
  • allocare sul mucchio e restituiscono un unique_ptr

ma in realtà il secondo punto deve essere utilizzato solo per i quelle poche classi in cui spostare la semantica non aiutano molto: il costo della semantica del movimento è solitamente proporzionale al rendimento di sizeof, ad esempio un std::array<T,10> ha una dimensione pari a 10*sizeof(T) quindi non è t così buono e potrebbe trarre vantaggio dall'allocazione dell'heap + unique_ptr.


Tangente: ci si fida già del compilatore. Ti fidi di avvertirti sugli errori, ti fidi di avvertirti su costrutti pericolosi/probabilmente errati, ti fidi di tradurre correttamente il tuo codice in assemblaggio della macchina, ti fidi di applicare un'ottimizzazione significativa per ottenere un'accelerazione decente .. Non confidare che un compilatore applichi il RVO in casi ovvi è come non fidarsi del cardiochirurgo con una banconota da $ 10: è l'ultima delle tue preoccupazioni. ;)

+1

Grazie mille per la tangente! :) – tmaric

1

Sono abbastanza sicuro che il compilatore eseguirà l'ottimizzazione del valore di ritorno per valueFun. I casi principali in cui ottimizzazione valore di ritorno non può essere applicata dal compilatore sono:

  • ritorno parametri
  • ritornano un oggetto diverso, basato su un condizionale

quindi l'auto_ptr non è necessario, e sarebbe ancora più lento a causa del dover utilizzare l'heap.

Se sei ancora preoccupato dei costi di spostamento di un vettore così grande, potresti voler utilizzare la semantica di spostamento (std::vector aCopy(std::move(otherVector)) di C++ 11. Questi sono quasi veloci come RVO e possono essere utilizzati ovunque (è garantito anche per essere utilizzato per i valori di ritorno quando RVO non è in grado di essere utilizzato.)

credo compilatori più moderni semantica sostegno spostare (o riferimenti rvalue tecnicamente), a questo punto

+0

Il "abbastanza sicuro" è ciò che mi disturba un po '. :) Dal mio punto di vista, se devo eseguire questa cosa su centinaia di core e se crescerà con il tempo, ho bisogno di essere sicuro al 100% di ciò che fa il codice. – tmaric

Problemi correlati