C# 为什么我的Parallel.ForAll调用最终使用单个线程?
我最近一直在使用PLINQ来执行一些数据处理 基本上我有大约4000个时间序列(因此基本上是C# 为什么我的Parallel.ForAll调用最终使用单个线程?,c#,.net,plinq,C#,.net,Plinq,我最近一直在使用PLINQ来执行一些数据处理 基本上我有大约4000个时间序列(因此基本上是字典的实例),我把它们存储在一个名为时间序列的列表中 要执行我的操作,我只需执行以下操作: timeSeries.AsParallel().ForAll(x=>myOperation(x)) 如果我看一下我的不同内核发生了什么,我会注意到,首先,我所有的CPU都在使用,我在控制台(我在那里输出一些日志)上看到几个时间序列同时被处理 然而,这个过程很长,大约45分钟后,日志清楚地表明只有一个线程在工
字典的实例),我把它们存储在一个名为时间序列的列表中
要执行我的操作,我只需执行以下操作:
timeSeries.AsParallel().ForAll(x=>myOperation(x))
如果我看一下我的不同内核发生了什么,我会注意到,首先,我所有的CPU都在使用,我在控制台(我在那里输出一些日志)上看到几个时间序列同时被处理
然而,这个过程很长,大约45分钟后,日志清楚地表明只有一个线程在工作。为什么呢
我试着对它进行一些思考,我意识到timeSeries
在列表的开头和结尾包含了从myOperation
的角度来看更容易处理的实例。因此,我想知道PLINQ使用的算法是否包括将4000个实例拆分为4个核,每个核1000个。然后,当内核完成其工作分配时,它将返回空闲状态。这意味着其中一个核心可能面临更大的工作量
我的理论是正确的还是有其他可能的解释
在运行列表之前,我应该先洗牌吗?或者我可以使用某种并行参数来解决这个问题吗?你的理论可能是正确的,尽管有一种叫做“工作教学”的方法可以解决这个问题。我不知道为什么这在这里不起作用。在外端有很多(>=几十个)大型作业,还是只有几个
除了洗牌数据外,您还可以将其用于接受。那会让你更好地平衡工作
旁注:在这种情况下,我更喜欢Parallel.ForEach()
,更多选项和更简洁的语法。据我所知,工作窃取在任务上有效,而不是在PLINQ中的迭代上。如果一个任务从集合中获取一组要处理的项目,其他任务将无法窃取这些项目。此外,此处可能不需要自定义分区器,这可能就足够了。@svick-您可能是对的,但这是否会指向创建一组任务的for循环?看起来很笨拙。