TPL强制更高的并行性

时间:2017-05-24 12:40:29

标签: c# .net multithreading task-parallel-library

Tasks排队到 ThreadPool 时,代码依赖于默认TaskScheduler来执行它们。在我的代码示例中,我可以看到7 Tasks最大值在不同的线程上并行执行。

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();

有没有办法强制调度程序在其他线程上启动更多Tasks?或者是否有更多"慷慨"框架中的调度程序没有实现自定义程序?

修改

添加ThreadPool.SetMinThreads(100, X)似乎可以解决问题,我假设等待释放线程,因此池认为它可以启动另一个,然后立即恢复。

  

默认情况下,最小线程数设置为系统上的处理器数。您可以使用SetMinThreads方法来增加最小线程数。但是,不必要地增加这些值可能会导致性能问题。如果太多任务同时启动,则所有任务可能看起来都很慢。在大多数情况下,线程池将使用自己的算法来分配线程,从而表现更好。将最小值降低到小于处理器数量也会影响性能。

从这里开始:https://msdn.microsoft.com/en-us/library/system.threading.threadpool.setminthreads(v=vs.110).aspx

我删除了AsParallel因为它不相关而且似乎让读者感到困惑。

4 个答案:

答案 0 :(得分:3)

  

有没有办法强制调度程序在其他线程上启动更多任务?

不能拥有比拥有CPU核心更多的执行线程。这就是计算机的工作原理。如果你使用更多的线程,那么你的工作实际上将完成更慢,因为线程必须交换进出核心才能运行。

  

还是有更多的"慷慨的"框架中的调度程序没有实现自定义程序?

PLINQ已经过调整,可以最大限度地利用硬件。

如果将Thread.Sleep调用替换为实际使用CPU的内容(例如while (true) ;),然后在任务管理器中查看CPU使用情况,则可以自行查看。我的期望是PLINQ在这个例子中使用的7或8个线程都是你的机器可以处理的。

答案 1 :(得分:0)

试试这个:

您可以设置工作线程数(第一个参数)。

答案 2 :(得分:0)

使用WithDegreeOfParallelism扩展程序:

Enumerable.Range(0, 100).AsParallel().WithDegreeOfParallelism(x).Select(...

答案 3 :(得分:0)

可以使用ThreadPool.SetMinThread

来解释它的有用链接

https://gist.github.com/JonCole/e65411214030f0d823cb#file-threadpool-md