2012-05-14 27 views
7

Tôi đang sử dụng C++ 11 trên Mac OS Xcode 4.3.2 std :: async sử dụng cùng một chuỗi và mã của tôi không đạt được tính song song. Trong mẫu mã dưới đây tôi muốn tạo ra 10 chủ đề mới. Trong mỗi chủ đề tôi muốn tính căn bậc hai của biến đầu vào và đặt kết quả theo lời hứa. trong chức năng chính tôi muốn hiển thị các kết quả tính từ chủ đề. Tôi đang gọi std :: async với chính sách khởi động :: async, Vì vậy, tôi mong đợi nó để tạo ra một chủ đề mới (10 lần).std :: async sử dụng cùng một luồng và mã của tôi không đạt được tính song song.

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

    } 

Tuy nhiên nếu tôi sử dụng std :: thread, thì tôi có thể đạt được tính song song.

#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

Việc thực hiện của 'thread' thư viện trên GCC cũ là không thực sự chức năng. Hãy thử nó trên một cái gì đó không cổ đại. – pmr

+0

@pmr: Tôi nghĩ Clang là trình biên dịch mặc định trong Xcode 4.2+? – ildjarn

+0

@ildjarn Bạn nói đúng, dĩ nhiên. Tôi nhầm 4.3.2 có nghĩa là một phiên bản gcc (XCode sử dụng gcc 4.something trong một thời gian dài). – pmr

Trả lời

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

dòng này trả về một future nhưng bởi vì bạn không gán nó vào bất cứ điều gì destructor của tương lai chạy ở phần cuối của báo cáo kết quả, trong đó khối và chờ đợi kết quả bằng cách gọi std::future::wait()

Tại sao bạn có tự gọi std::async với một lời hứa, khi nó trả về một tương lai không? Điểm của async là bạn không cần phải sử dụng một lời hứa theo cách thủ công, điều đó được thực hiện nội bộ cho bạn.

Rewrite foo() của bạn để trở double sau đó gọi nó với 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

Khi chúng tôi đang ở trong vòng lặp, đó là mã tuần tự. Không cần mutex ở đây. – Jagannath

+0

Tôi muốn sử dụng Promise và async cùng nhau. Điều đó có nghĩa là nếu chúng ta sử dụng Promise với std :: async thì nó không thể hoạt động như async và luôn hoạt động như một cuộc gọi đồng bộ? –

+0

@Jagannath: không, trong lần lặp đầu tiên bạn đã chờ đợi một tương lai, có chín chủ đề vẫn có thể đang chạy và ghi vào cout. Trong lần lặp thứ hai, vẫn có thể có 8 chủ đề được viết cho cout, v.v. (@sehe cảm ơn vì sự cải tiến mã) –

Các vấn đề liên quan