Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

std::async uses same thread and my code does not achieve parallelism.

I am using C++11 on Mac OS Xcode 4.3.2 std::async uses same thread and my code does not achieve parallelism. In sample code below I want to create 10 new threads. In each thread I want to calculate square root of input variable and set the result in promise. in main function I want to display the results calculated from threads. I am calling std::async with policy launch::async, So I expect it to create a new thread(10 times).

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

    }

However if I use std::thread, then I can achieve parallelism.

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

    }
like image 706
Vijay Kumar Avatar asked May 14 '12 13:05

Vijay Kumar


People also ask

Does STD async use threads?

If the async flag is set, then a callable function will be executed in a separate thread. If the deferred flag is set, a callable function will be stored together with its arguments, but the std::async function will not launch a new thread.

Does STD async run on a separate thread?

The function template async runs the function f asynchronously (potentially in a separate thread which might be a part of a thread pool) and returns a std::future that will eventually hold the result of that function call.

What is async C++?

As the name indicates, C++ async is a function template fn, which takes functions or function objects as arguments (basically called callbacks) and runs them asynchronously. It returns the std:: the future object which is used to keep the result of the above function. The result is stored in the shared state.


1 Answers

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

This line returns a future but because you do not assign it to anything the future's destructor runs at the end of the statement, which blocks and waits for the result by calling std::future::wait()

Why are you manually calling std::async with a promise, when it returns a future anyway? The point of async is that you don't need to manually use a promise, that's done internally for you.

Rewrite your foo() to return double then call it with 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";
}
like image 144
Jonathan Wakely Avatar answered Sep 20 '22 17:09

Jonathan Wakely