Boost logo

Boost :

Subject: Re: [boost] [threadpool] draft n2276 - launch_in_pool
From: Dean Michael Berris (mikhailberis_at_[hidden])
Date: 2008-11-21 09:15:13


Hi Neil,

On Fri, Nov 21, 2008 at 10:01 PM, Neil Groves <neil_at_[hidden]> wrote:
> Hi!
>
> A static threadpool is not inherently unreasonable, but only supporting a
> single instance of threadpool is.

I agree, to some extent. Let me defer why I think so later.

> The optimal number of worker-threads in
> the thread pool depends on the problem and is not always equal to the number
> of available cores. An example of a case where I get better performance
> running more threads than available cores is where I have synchronous I/O on
> each of the threads that means that on average 2 out of 4 threads are in the
> blocked state. It is measurably better to add two more threads into the
> thread pool and allow the CPU to be optimally utilised. There are clearly
> design alternatives using asynchronous I/O etc. but this is merely intended
> as an example.
>

Again I agree to some extent. However, it's not the standard's job I
think to optimize the tasks that you're running in the thread pool
anyway -- I think there are a lot of ways to make the thread pools
more effective/efficient (through work-stealing on waits, etc.) but
that's only for an efficient implementation of a thread pool.

> Since the optimal number of threads depends on the tasks performed on the
> threads it follows that only having one thread-pool with one configuration
> per process is a bad idea.
>

True. But I wouldn't be surprised if there would be a proposal to an
overload to the launch_in_pool(...) method which takes a "concrete" or
"existing" pool that is either referred to by a handle/proxy or by
reference.

Something like:

// version 1
template <ThreadPool pool_type, PackagedTask task_type>
typename task_type::future_type launch_in_pool(task_type task,
pool_type & pool) {
  pool.post(task);
  return task.get_future();
}

// version 2
template <PackagedTask task_type>
typename task_type::future_type launch_in_pool(task_type task) {
  static std::default_thread_pool __pool_instance;
  __pool_instance.post(task);
  return task.get_future();
}

Above, version 1 would have an overload that takes a reference to an
existing thread pool to which a task gets posted to. Also, version 2
will use a static local pool, intialized before main() is called by
the main thread, and destroyed when main() finishes.

I hope this makes sense.

-- 
Dean Michael C. Berris
Software Engineer, Friendster, Inc.

Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk