2012-05-14 11 views
7

Estoy usando C++ 11 en Mac OS Xcode 4.3.2 std :: async usa el mismo subproceso y mi código no logra el paralelismo. En el siguiente código de muestra, quiero crear 10 nuevos hilos. En cada hilo, quiero calcular la raíz cuadrada de la variable de entrada y establecer el resultado en promesa. en la función principal, quiero mostrar los resultados calculados a partir de los hilos. Estoy llamando a std :: async con policy launch :: async, así que espero que cree un nuevo hilo (10 veces).std :: async usa el mismo subproceso y mi código no logra el paralelismo.

#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; 

    } 

Sin embargo, si uso std :: thread, entonces puedo lograr el paralelismo.

#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

La aplicación de la 'thread' biblioteca en GCCS mayores no es realmente funcional. Pruébalo en algo no antiguo. – pmr

+0

@pmr: ¿Creí que Clang era el compilador predeterminado en Xcode 4.2+? – ildjarn

+0

@ildjarn Tienes razón, por supuesto. Me confundí con el 4.3.2 para indicar una versión de gcc (XCode usó gcc 4. algo durante mucho tiempo). – pmr

Respuesta

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

Esta línea devuelve un future sino porque no se asigna a nada destructor del futuro se ejecuta al final de la declaración, que bloquea y espera el resultado llamando std::future::wait()

Por qué ¿Estás llamando manualmente al std::async con una promesa, cuando devuelve un futuro de todos modos? El objetivo de la asincronización es que no necesitas usar una promesa manualmente, eso se hace internamente para ti.

reescribir su foo() para volver double entonces lo llaman 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 vez que estamos en el bucle for, es un código secuencial. No es necesario mutex aquí. – Jagannath

+0

Quería hacer uso de Promise y async juntos. ¿Eso significa que si usamos Promise with std :: async, entonces no puede comportarse como una sincronización y siempre comportarse como una llamada de sincronización? –

+0

@Jagannath: no, en la primera iteración que esperaste para un futuro, hay nueve hilos que todavía podrían estar ejecutándose y escribiendo para cout. En la segunda iteración aún podría haber ocho hilos escribiendo para cout, etc. (@sehe gracias por las mejoras en el código) –

Cuestiones relacionadas