2012-05-14 17 views
7

Sto usando C++ 11 su Mac OS Xcode 4.3.2 std :: async utilizza lo stesso thread e il mio codice non raggiunge il parallelismo. Nel codice di esempio seguente voglio creare 10 nuovi thread. In ogni thread voglio calcolare la radice quadrata della variabile di input e impostare il risultato nella promessa. nella funzione principale voglio visualizzare i risultati calcolati dai thread. Sto chiamando std :: async con policy launch :: async, quindi mi aspetto che crei un nuovo thread (10 volte).std :: async utilizza lo stesso thread e il mio codice non raggiunge il parallelismo.

#include <mutex> 
    #include <future> 
    #include <thread> 
    #include <vector> 
    #include <cmath> 
    #include <iostream> 

    using namespace std; 
    mutex iomutex; 

    void foo(int i, promise<double> &&prms) 
    { 
     this_thread::sleep_for(chrono::seconds(2)); 
     prms.set_value(sqrt(i)); 
     { 
      lock_guard<mutex> lg(iomutex); 
      cout << endl << "thread index=> " << i << ", id=> "<< this_thread::get_id(); 
     } 
    } 

    int main() 
    { 
     { 
      lock_guard<mutex> lg(iomutex); 
      cout << endl << "main thread id=>"<< this_thread::get_id(); 
     } 
     vector<future<double>> futureVec; 
     vector<promise<double>> prmsVec; 

     for (int i = 0; i < 10; ++i) { 
      promise<double> prms; 
      future<double> ftr = prms.get_future(); 
      futureVec.push_back(move(ftr)); 
      prmsVec.push_back(move(prms)); 

      async(launch::async, foo, i, move(prmsVec[i])); 
     } 

     for (auto iter = futureVec.begin(); iter != futureVec.end(); ++iter) { 
      cout << endl << iter->get(); 
     } 

     cout << endl << "done"; 

     return 0; 

    } 

Tuttavia se uso std :: thread, quindi posso ottenere il parallelismo.

#include <mutex> 
    #include <future> 
    #include <thread> 
    #include <vector> 
    #include <cmath> 
    #include <iostream> 

    using namespace std; 
    mutex iomutex; 

    void foo(int i, promise<double> &&prms) 
    { 
     this_thread::sleep_for(chrono::seconds(2)); 
     prms.set_value(sqrt(i)); 
     { 
      lock_guard<mutex> lg(iomutex); 
      cout << endl << "thread index=> " << i << ", id=> "<< this_thread::get_id(); 
     } 
    } 

    int main() 
    { 
     { 
      lock_guard<mutex> lg(iomutex); 
      cout << endl << "main thread id=>"<< this_thread::get_id(); 
     } 
     vector<future<double>> futureVec; 
     vector<promise<double>> prmsVec; 
     vector<thread> thrdVec; 
     for (int i = 0; i < 10; ++i) { 
      promise<double> prms; 
      future<double> ftr = prms.get_future(); 
      futureVec.push_back(move(ftr)); 
      prmsVec.push_back(move(prms)); 

      thread th(foo, i, move(prmsVec[i])); 
      thrdVec.push_back(move(th)); 
     } 

     for (auto iter = futureVec.begin(); iter != futureVec.end(); ++iter) { 
      cout << endl << iter->get(); 
     } 
     for (int i = 0; i < 10; ++i) { 
      thrdVec[i].join(); 
     } 
     cout << endl << "done"; 

     return 0; 

    } 
+0

L'attuazione del 'thread' biblioteca in gcc alcune anziane non è davvero funzionale. Provalo su qualcosa di non antico. – pmr

+0

@ pmr: Pensavo che Clang fosse il compilatore predefinito in Xcode 4.2+? – ildjarn

+0

@ildjarn Hai ragione, certo. Ho scambiato il 4.3.2 per indicare una versione gcc (XCode ha usato gcc 4.qualcosa per molto tempo). – pmr

risposta

16
  async(launch::async, foo, i, move(prmsVec[i])); 

Questa linea restituisce una future ma perché non si assegna a nulla distruttore del futuro si avvia alla fine della dichiarazione, che blocca e attende il risultato chiamando std::future::wait()

Perché stai chiamando manualmente std::async con una promessa, quando restituisce comunque un futuro? Il punto di asincrono è che non è necessario utilizzare manualmente una promessa, che è fatta internamente per te.

riscrivere la foo() per tornare double poi lo chiamano con async

#include <mutex> 
#include <future> 
#include <thread> 
#include <vector> 
#include <cmath> 
#include <iostream> 

using namespace std; 
mutex iomutex; 

double foo(int i) 
{ 
    this_thread::sleep_for(chrono::seconds(2)); 
    lock_guard<mutex> lg(iomutex); 
    cout << "\nthread index=> " << i << ", id=> "<< this_thread::get_id(); 
    return sqrt(i); 
} 

int main() 
{ 
    cout << "\nmain thread id=>" << this_thread::get_id(); 
    vector<future<double>> futureVec; 

    for (int i = 0; i < 10; ++i) 
     futureVec.push_back(async(launch::async, foo, i)); 

    for (auto& fut : futureVec) 
    { 
     auto x = fut.get(); 
     lock_guard<mutex> lg(iomutex); 
     cout << endl << x; 
    } 

    cout << "\ndone\n"; 
} 
+0

Una volta che siamo nel ciclo for, è un codice sequenziale. Non c'è bisogno di mutex qui. – Jagannath

+0

Volevo fare uso di Promise e async insieme. Significa che se usiamo Promise con std :: async allora non può comportarsi come asincrono e comportarsi sempre come una chiamata di sincronizzazione? –

+0

@Jagannath: no, alla prima iterazione hai aspettato un futuro, ci sono nove thread che potrebbero ancora essere in esecuzione e scrivere in cout. Nella seconda iterazione potrebbero ancora esserci otto thread che scrivono in cout ecc. (@sei grazie per i miglioramenti del codice) –

Problemi correlati