2012-06-05 11 views
13

Breve introduzione: Sto lavorando su un codice multithread e devo condividere oggetti allocati dinamicamente tra due thread. Per rendere il mio codice più pulito (e meno soggetto a errori), voglio "cancellare" esplicitamente gli oggetti in ogni thread ed è per questo che voglio usare shared_ptr.Overhead e implementazione dell'utilizzo di shared_ptr

Prima domanda:

Voglio sapere se l'attuazione di -> operator in shared_ptr ha un certo overhead in più (per esempio più grande allora unique_ptr) durante la fase di esecuzione. Gli oggetti di cui sto parlando sono in genere istanze longlife copiate solo una volta dopo la creazione (quando li distribuisco tra i thread), quindi accedo solo ai metodi e ai campi di questi oggetti.

Sono consapevole che lo shared_ptr protegge solo il conteggio dei riferimenti.

Seconda domanda:

Quanto bene sono shared_ptr ottimizzati in libstdC++? Utilizza sempre il mutex o sfrutta le operazioni atomiche (mi concentro sulle piattaforme x86 e ARM)?

+3

In una buona implementazione di 'shared_ptr', ci dovrebbe essere zero overhead durante il dereferenziamento del puntatore tramite' -> '. Non ho familiarità con libstdC++, quindi non posso rispondere alla tua seconda domanda. Hai le intestazioni, però, in modo che tu possa facilmente scoprire dando un'occhiata a come è implementato. –

+2

Se il codice è multithread, il puntatore condiviso di GCC usa uno 'std :: atomic ' o qualcosa del genere per il contatore di riferimento; che si tratti di un atomico hardware (senza blocco) reale dipende dalla versione del compilatore - credo che sia stato migliorato in GCC 4.7.0. –

+3

Copia/assegnazione/uscita dall'ambito ha un overhead aggiuntivo a causa dell'incremento del thread-count del conto. 'operator->' sembra esattamente uguale a quello del buon vecchio 'auto_ptr', cioè ci si può aspettare un sovraccarico pari a zero. – Damon

risposta

14

Prima domanda: usando operator->

Tutte le implementazioni che ho visto hanno una cache locale di T* proprio nella classe shared_ptr<T> modo che il campo è in pila, operator-> ha quindi un analogo costo per l'utilizzo di uno stack locale T*: nessun sovraccarico.

Seconda domanda: mutex/Atomics

mi aspetto libstdC++ da utilizzare atomiche su piattaforma x86, sia per mezzo di servizi standard o specifici intrinseci g ++ (nelle versioni precedenti). Credo che l'implementazione di Boost lo abbia già fatto.

Non posso, tuttavia, commentare ARM.

Nota: C++ 11 introduce la semantica del movimento, molte copie sono naturalmente evitate nell'uso di shared_ptr.

Nota: leggere sull'uso del corretto di shared_ptrhere, è possibile utilizzare riferimenti a shared_ptr (const o meno) per evitare la maggior parte delle copie/distruzione in generale, per cui le prestazioni di coloro che non è troppo importante.

+0

nella risposta allegata si dice che usi 'make_shared'. Mi chiedo come utilizzare questo modello sulla lista di inizializzazione del costruttore? Esempio, la classe 'Foo' ha campo' shared_ptr num', quindi il costruttore dovrebbe assomigliare a questo: 'Foo :: Foo (void): num (move (make_shared (new int (30)))) {...}' ? – Goofy

+2

@Goofy: no, con 'make_shared' non si esegue esplicitamente il' new' e d'altra parte è necessario passare esplicitamente il tipo dell'oggetto creato; anche la chiamata a 'move' non è necessaria su un temporaneo. Quindi produce: 'Foo :: Foo(): num (std :: make_shared (30)) {}' –

+0

Ok, ottimo :) Mi sto ancora abituando ai rvalues ​​in C++;) – Goofy

12

Shared_ptr di GCC non utilizzerà il blocco o l'atomica nel codice a thread singolo. Nel codice multi-thread utilizzerà le operazioni atomiche se un'istruzione atomica di confronto-e-swap è supportata dalla CPU, altrimenti i conteggi di riferimento sono protetti da un mutex. In i486 e versioni successive utilizza atomics, i386 non supporta cmpxchg, quindi utilizza un'implementazione basata su mutex. Credo che ARM usi l'atomica per l'architettura ARMv7 e in seguito.

(lo stesso vale per std::shared_ptr e std::tr1::shared_ptr.)

+1

Come fa GCC sapere se il il codice è/sarà multi-thread o no? –

+0

@DrewNoakes: devi dirlo con un #define. –

+0

Avete un riferimento per questo? Ho fatto un po 'di ricerche e non riesco a trovarne uno. –