C# 带并行度(N>;CPU计数)

C# 带并行度(N>;CPU计数),c#,plinq,C#,Plinq,在我的系统中,线程数从未超过CPU数。 我可以使用PLINQ并在每个CPU上获得多个线程吗?简短回答:不可以 线程的数量取决于.Net Framework运行时。没有用于控制TPL(任务并行库)使用的线程数的开发人员控件 编辑 多亏了其他一些反馈:实际上可以(但不推荐)手动控制线程池中的线程数量,PLINQ和TPL使用这些线程 我认为,任何并行化问题都需要仔细考虑、仔细构造和测试。这里面有很多微妙之处。简短回答:不 线程的数量取决于.Net Framework运行时。没有用于控制TPL(任务并行

在我的系统中,线程数从未超过CPU数。 我可以使用PLINQ并在每个CPU上获得多个线程吗?

简短回答:不可以

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

编辑

多亏了其他一些反馈:实际上可以(但不推荐)手动控制线程池中的线程数量,PLINQ和TPL使用这些线程

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

简短回答:不

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

编辑

多亏了其他一些反馈:实际上可以(但不推荐)手动控制线程池中的线程数量,PLINQ和TPL使用这些线程


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

PLINQ使用爬山算法来确定TPL使用的线程池的最佳大小。我认为,如果在任务中投入大量I/O,那么可以看到比cpu数量更多的线程


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

PLINQ使用爬山算法来确定TPL使用的线程池的最佳大小。我认为,如果在任务中投入大量I/O,那么可以看到比cpu数量更多的线程


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

如果调用外部web API,可能会达到并发连接的极限,即设置为2。在应用程序开始时,请执行以下操作:

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 
*/
});
如果有帮助的话,试试看。如果没有,那么在您尝试并行化的例程中可能存在其他瓶颈


另外,正如其他响应者所说,ThreadPool根据负载决定要启动多少线程。在我使用TPL的经验中,我发现线程数量随着时间的推移而增加:应用程序运行的时间越长,负载越重,线程就越多。

如果调用外部web API,可能会达到并发连接的限制,即设置为2。在应用程序开始时,请执行以下操作:

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 
*/
});
如果有帮助的话,试试看。如果没有,那么在您尝试并行化的例程中可能存在其他瓶颈


另外,正如其他响应者所说,ThreadPool根据负载决定要启动多少线程。在我使用TPL的经验中,我发现线程数量随着时间的推移而增加:应用程序运行的时间越长,负载越重,线程就越多。

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

System.Net.ServicePointManager.DefaultConnectionLimit = 4096;
System.Net.ServicePointManager.Expect100Continue = false;
基本上,它记录当前并发执行的迭代次数,然后保存遇到的最大值

结果相差很大,在15到25之间,但总是比我的计算机拥有的CPU数量(4)多得多。增加睡眠时间会增加并发线程的最大数量。因此,这里的限制因素似乎是
ThreadPool
:它将缓慢地创建新线程,特别是当作业相对较快地完成时

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


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

我用以下代码测试:

System.Net.ServicePointManager.DefaultConnectionLimit = 4096;
System.Net.ServicePointManager.Expect100Continue = false;
基本上,它记录当前并发执行的迭代次数,然后保存遇到的最大值

结果相差很大,在15到25之间,但总是比我的计算机拥有的CPU数量(4)多得多。增加睡眠时间会增加并发线程的最大数量。因此,这里的限制因素似乎是
ThreadPool
:它将缓慢地创建新线程,特别是当作业相对较快地完成时

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


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

PLUNQ不适合这种情况。 我发现下一篇文章对我很有用。
PLINQ不适合这种情况。 我发现下一篇文章对我很有用。

这有什么意义?性能不会提高。@GSerg:如果出现某种阻塞IO,性能可能会提高。不推荐。如果我是你,我会调查TPL数据流。或者如果你想使用纯TPL,请查看Parallel.For和Parallel。ForEach@Vladimir这就是阻塞IO的定义;您启动一个IO操作,然后让一个线程坐在那里不做任何事情等待它完成,而不是使用异步,这样您就可以在操作完成时做一些事情,而不用让一个线程等待该操作。@Vladimir:I'm not blocking IO.语句直接与“每个任务只会将请求发送到外部慢速API,并等待~3秒以获得响应”。您在IO上阻塞了~3秒。这有什么意义?性能不会提高。@GSerg:可能可以