Search code examples
visual-studio-2013ppl

Does PPL take the load of the system into account when creating threads or not?


I am starting to use PPL to create tasks and dispatch them [possibly] to other threads, like this:

Concurrency::task_group  tasks;
auto simpleTask = Concurrency::make_task(&simpleFunction);
tasks.run(simpleTask);

I experimented with a small application that creates a task every second. Task performs heavy calculations during 5 seconds and then stops.

I wanted to know how many threads PPL creates on my machine and whether the load of the machine influences the number of threads or the tasks assigned to the threads. When I run one or more instances of my application on my 12-core machine, I notice this:

  • When running 1 application, it creates 6 threads. Total CPU usage is 50%.
  • When running 2 applications, both of them create 6 threads. Total CPU usage is 100% but my machine stays rather responsive.
  • When running 3 applications, all of them create 6 threads (already 18 threads in total). Total CPU usage is 100%.
  • When running 4 applications, I already have 24 threads in total.

I investigated the running applications with Process Explorer and with 4 applications I can clearly see that they all have 6 (sometimes even 12) threads that are all trying to consume as much CPU as possible.

PPL allows you to limit the number of threads by configuring the default scheduler, like this:

Concurrency::SchedulerPolicy policy(1, Concurrency::MaxConcurrency,2);
Concurrency::Scheduler::SetDefaultSchedulerPolicy(policy);

With this you statically limit the number of threads (2 in this case). It can be handy if you know beforehand that on a server with 24 cores there are 10 simultaneous users (so you can limit every application to 2 threads), but if one of the 10 users is working late, he still only uses 2 threads, while the rest of the machine is idling.

My question: is there a way to configure PPL so that it dynamically decides how many threads to create (or keep alive or keep active) based on the load of the machine? Or does PPL already does this by default and my observations are incorrect.

EDIT: I tried starting more instances of my test application, and although my machine remains quite responsive (I was wrong in the original question) I can't see the applications reducing their number of simultaneous actions.


Solution

  • The short answer to your question is "No." The default PPL scheduler and resource manager will only use process-local information to decide when to create/destroy threads. As stated in the Patterns and Practices article on MSDN:

    The resource manager is a singleton that works across one process. It does not coordinate processor resources across multiple operating-system processes. If your application uses multiple, concurrent processes, you may need to reduce the level of concurrency in each process for optimum efficiency.

    If you're willing to accept the complexity, you may be able to implement a custom scheduler/resource manager to take simple system-level performance readings (e.g. using the PDH functions) to achieve what you want.