Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Control degree of parallelism with std::async

Is there a way to explicitly set/limit the degree of parallelism (= the number of separate threads) used by std::async and related classes?

Perusing the thread support library hasn’t turned up anything promising.

As close as I could figure out, std::async implementations (usually?) use a thread pool internally. Is there are standardised API to control this?

For background: I’m in a setting (shared cluster) where I have to manually limit the number of cores used. If I fail to do this, the load sharing scheduler throws a fit and I’m penalised. In particular, std::thread::hardware_concurrency() holds no useful information, since the number of physical cores is irrelevant for the constraints I’m under.

Here’s a relevant piece of code (which, in C++17 with parallelism TS, would probably be written using parallel std::transform):

auto read_data(std::string const&) -> std::string;

auto multi_read_data(std::vector<std::string> const& filenames, int ncores = 2) -> std::vector<std::string> {
    auto futures = std::vector<std::future<std::string>>{};

    // Haha, I wish.
    std::thread_pool::set_max_parallelism(ncores);

    for (auto const& filename : filenames) {
        futures.push_back(std::async(std::launch::async, read_data, filename));
    }

    auto ret = std::vector<std::string>(filenames.size());
    std::transform(futures.begin(), futures.end(), ret.begin(),
            [](std::future<std::string>& f) {return f.get();});
    return ret;
}

From a design point of view I’d have expected the std::execution::parallel_policy class (from parallelism TS) to allow specifying that (in fact, this is how I did it in the framework I designed for my master thesis). But this doesn’t seem to be the case.

Ideally I’d like a solution for C++11 but if there’s one for later versions I would still like to know about it (though I can’t use it).

like image 303
Konrad Rudolph Avatar asked Jul 14 '17 15:07

Konrad Rudolph


2 Answers

No. std::async is opaque, and you have no control over it's usage of threads, thread pools or anything else. As a matter of fact, you do not even have any guarantee that it would use a thread at all - it might as well execute in the same thread (potentially, note @T.C. comment below), and such implementation would still be conformant.

C++ threading library was never supposed to handle fine-tuning of OS / hardware specifics of threads management, so I am afraid, in your case you will have to code for the proper support yourself, potentially using OS-provided thread control primitives.

like image 133
SergeyA Avatar answered Sep 18 '22 13:09

SergeyA


As other people have noted, std::async doesn't let you do this.

Yet

You're describing one of the simpler use-cases of Executors which are currently still bouncing around the design-space of C++ Standardisation, specifically right now in Study Group 1: Concurrency.

Since reading WG21 standards proposals can be a slog, they authors have helpfully linked to both a prototype header-only reference implementation and some example code.

It even includes a static thread pool, and an example of almost exactly what you want: async_1.cpp

#include <experimental/thread_pool>
#include <iostream>
#include <tuple>

namespace execution = std::experimental::execution;
using std::experimental::static_thread_pool;

template <class Executor, class Function>
auto async(Executor ex, Function f)
{
  return execution::require(ex, execution::twoway).twoway_execute(std::move(f));
}

int main()
{
  static_thread_pool pool{1};
  auto f = async(pool.executor(), []{ return 42; });
  std::cout << "result is " << f.get() << "\n";
}

Thank you to @jared-hoberock for pointing me at P0668R0 as the much simpler followup to P0443R1 which I had referenced in an earlier version of this answer.

This simplification has been applied, and now there's both a paper describing the rationale (P0761R0), and a much simpler version of the standard wording in P0443R2.


As of July 2017, the only actual guess I've seen on delivery of this is: Michael Wong, editor of the Concurrency TS --- the standardisation vehicle for Executors --- feels "confident that it will make it into C++20".

like image 42
TBBle Avatar answered Sep 18 '22 13:09

TBBle