2013-02-13 4 views
13

Sto provando ad accelerare un programma usando std :: async. Diciamo che ho una funzionePerché std :: async copia i suoi const e argomenti?

T* f (const T& t1, const T& t2, const T& t3) 

dove T è un tipo che è costoso da copiare. Ho parecchie chiamate indipendenti di f con argomenti diversi e provo a parallelizzarle con std :: async approssimativamente come questo: (dove m_futures è un std :: vettore di futures del tipo corretto).

for (...) { 
    m_futures.push_back (
     std::async(
      std::launch::async, 
      f, 
      a,b,c)); 
} 

Ho osservato che il codice sopra riportato rallenta l'esecuzione del mio programma. L'ho passato con gdb e quando viene creato il futuro, il costruttore di copie di T è chiamato tre volte. Perché? Gli argomenti a, b, c sono allocati su heap, ma forse il compilatore non ne sa nulla? Posso renderlo esplicito in qualche modo?

È sempre il caso che std :: async crea copie degli argomenti, anche se devono essere passati per riferimento const? Posso evitare questo in qualche modo? Nella mia mente ingenua, dovrebbe esserci solo un puntatore passato alle diverse invocazioni della funzione (che legge comunque solo dalla memoria). Sto usando gcc-4.6.3 su Linux se questo è importante.

risposta

19

Non sarebbe sicuro per memorizzare i riferimenti solo, dal momento che non c'è niente da garantire l'assenza di gare di dati (e più profondamente, la mera esistenza di oggetti, come @utapistim detto nel suo messaggio purtroppo cancellato).

Se si vuole realmente un riferimento piuttosto che una copia, e si 're pronto a scommettere la vostra vita su questo essere corretto, allora si può semplicemente utilizzare un wrapper di riferimento:

std::async(std::launch::async, f, std::cref(a), std::cref(b), std::cref(c)) 
+1

Per curiosità, cosa succede se cambio l'interfaccia e passo esplicitamente un puntatore? Sarebbe equivalente all'utilizzo di wrapper di riferimento? – Thomas

+0

@Thomas: Sì. I wrapper di riferimento * sono essenzialmente * puntatori. Non utilizzare puntatori nudi in C++ (tranne che come membri di una classe privata). Preferisci i wrapper di riferimento. –

+0

OK, grazie, non sapevo nulla sul riferimento. – Thomas