WithDegreeOfParallelism(N> CPU计数)

时间:2013-10-28 15:13:09

标签: c# plinq

System.Threading.ThreadPool.SetMaxThreads(50, 50);
File.ReadLines().AsParallel().WithDegreeOfParallelism(100).ForAll((s)->{
/*
some code which is waiting external API call 
and do not utilize CPU 
*/
});

我的系统中的线程计数从未超过CPU数。 我可以使用PLINQ并为每个CPU获取多个线程吗?

5 个答案:

答案 0 :(得分:2)

如果您正在调用外部Web API,则可能达到并发同时连接的限制,该连接设置为2.在应用程序开始时,请执行以下操作:

System.Net.ServicePointManager.DefaultConnectionLimit = 4096;
System.Net.ServicePointManager.Expect100Continue = false;

尝试这有帮助。如果没有,那么您尝试并行化的例程中可能存在其他一些瓶颈。

此外,就像其他响应者所说的那样,ThreadPool根据负载决定启动多少个线程。根据我使用TPL的经验,我发现线程随着时间的推移而增加:应用程序运行的时间越长,负载越重,线程就越多。

答案 1 :(得分:1)

PLINQ使用爬山算法来确定TPL使用的线程池的最佳大小。我认为如果你在你的任务中放了很多I / O,那么看到比cpu计数更多的线程是可爱的。

那就是说,我从未见过比cpu计数更多的线程:)。但也许我从未遇到过正确的情况。

答案 2 :(得分:0)

简短回答:不。

线程数量仅限于.Net Framework运行时。没有开发人员控制来控制TPL(任务并行库)使用的线程数。

修改

感谢其他一些反馈:实际上可以 - 但不建议 - 手动控制ThreadPool中的线程数,PLINQ和TPL使用它。

我认为任何并行化问题都需要仔细考虑,并仔细构建和测试。这里有很多细微之处。

答案 3 :(得分:0)

我使用以下代码对此进行了测试:

var lines = Enumerable.Range(0, 200).ToArray();
int currentThreads = 0;
int maxThreads = 0;
object l = new object();
lines.AsParallel().WithDegreeOfParallelism(100).ForAll(
    s =>
    {
        lock (l)
        {
            currentThreads++;
            if (currentThreads > maxThreads)
            {
                maxThreads = currentThreads;
                Console.WriteLine(maxThreads);
            }
        }
        Thread.Sleep(3000);
        lock (l)
        {
            currentThreads--;
        }
    });

Console.WriteLine();
Console.WriteLine(maxThreads);

基本上,它记录当前正在执行的迭代次数,然后保存遇到的最大值。

结果差异很大,在15到25之间,但它总是远远超过我的计算机所拥有的CPU数量(4)。增加休眠时间会增加并发线程的最大数量。所以看起来这里的限制因素是ThreadPool:它会慢慢地创建新线程,尤其是当作业相对较快地完成时。

如果要增加使用的线程数,则需要使用SetMinThreads()(不是SetMaxThreads())。如果我将最小值设置为50,则实际使用的线程数约为60。

但是有几十个线程除了等待之外什么都不做,效率非常低,特别是在内存消耗方面。您应该考虑使用异步方法。

答案 4 :(得分:0)

PLINQ不适合这种情况。 我发现下一篇文章对我有用。 http://msdn.microsoft.com/en-us/library/hh228609(v=vs.110).aspx