vendredi 9 juin 2017

A pooled async object for better performance

I read a bit about std::async and by I am sadly a bit disappointed from what I've learned and tried so far.

Now I "implemented" a litte std::async replacer with a thread pool behind the scenes to try around with the game I am just working on in my freetime. The async replacer is neither beautiful, nor elegant or optimized, but still it's outperforming the std::async if you use it with the std::launch::async flag.

The code is quite minimal:

namespace util
{
    template <class R, class T> std::future<R> async(const T& task)
    {
        std::shared_ptr<std::promise<R> > result = std::make_shared<std::promise<R> >();

        //threadctrl::run is a call which runs tasks on an engine-global thread pool, which get's injected on initialization
        threadctrl::run(std::bind([](std::shared_ptr<std::promise<R> > result, const T& task)->void
        {
            try
            {
                result->set_value(task());
            }
            catch (...)
            {
                //not handled here
            }

        }, result, std::ref(task)));

        return result->get_future();
    }
}

A simple usage example would look like this:

int main()
{
    std::future<int> result = util::async<int>(std::bind(give5));

    //Do some other work

    std::cout << result.get();

    return 0;
}

My question is: Is there a really good reason to prefer the original std::async implementation over this approach in a gaming environment or is this just fine?

The performance of my minimal implementation is a lot better and I only use/need this very slim interface which would come very handy to me since I won't use deferred asyncs anyway.

Under windows 7 32 bit with an i5 4570 and 4gb of ram i get the following results:

0.001 milliseconds per util::async task (scheduling only)

0.006 milliseconds per std::async task (scheduling only)

Aucun commentaire:

Enregistrer un commentaire