Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

TPL force higher parallelism

When queuing Tasks to the ThreadPool, the code relies on the default TaskScheduler to execute them. In my code example, I can see that 7 Tasks maximum get executed in parallel on separate threads.

new Thread(() =>
{
    while (true)
    {
        ThreadPool.GetAvailableThreads(out var wt, out var cpt);
        Console.WriteLine($"WT:{wt} CPT:{cpt}");
        Thread.Sleep(500);
    }
}).Start();

var stopwatch = new Stopwatch();
stopwatch.Start();
var tasks = Enumerable.Range(0, 100).Select(async i => { await Task.Yield(); Thread.Sleep(10000); }).ToArray();
Task.WaitAll(tasks);
Console.WriteLine(stopwatch.Elapsed.TotalSeconds);
Console.ReadKey();

Is there a way to force the scheduler to fire up more Tasks on other threads? Or is there a more "generous" scheduler in the framework without implementing a custom one?

EDIT:

Adding ThreadPool.SetMinThreads(100, X) seems to do the trick, I presume awaiting frees up the thread so the pool think it can fire up another one and then it immediately resumes.

By default, the minimum number of threads is set to the number of processors on a system. You can use the SetMinThreads method to increase the minimum number ofthreads. However, unnecessarily increasing these values can cause performance problems. If too many tasks start at the same time, all of them might appear to be slow. In most cases, the thread pool will perform better with its own algorithm for allocating threads. Reducing the minimum to less than the number of processors can also hurt performance.

From here: https://msdn.microsoft.com/en-us/library/system.threading.threadpool.setminthreads(v=vs.110).aspx

I removed AsParallel as it is not relevant and it just seems to confuse readers.

like image 770
user4388177 Avatar asked Nov 26 '25 03:11

user4388177


1 Answers

Is there a way to force the scheduler to fire up more Tasks on other threads?

You cannot have more executing threads than you have CPU cores. This is just how computers work. If you use more threads, then your work will actually get done more slowly since the threads must swap in and out of the cores in order to run.

Or is there a more "generous" scheduler in the framework without implementing a custom one?

PLINQ is already tuned to make maximum use of the hardware.

You can see this for yourself if you replace the Thread.Sleep call with something that actually uses the CPU (e.g., while (true) ;), and then watch your CPU usage in Task Manager. My expectation is that the 7 or 8 threads used by PLINQ in this example is all your machine can handle.

like image 183
Stephen Cleary Avatar answered Nov 28 '25 17:11

Stephen Cleary



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!