并行处理并将列表拆分为两个 - 它是否加快了整个操作?

时间:2011-06-29 20:43:49

标签: c# optimization loops parallel-processing

我的操作需要检查数十万个矩阵(2D int数组),直到每个矩阵都被处理完毕,或者满足某个条件。基本上

For each matrix m in matricesList:
   if Function(m) returns true: exit
   else continue

我对优化Function()不感兴趣。我很想知道的是,我是否可以将矩阵列表分成两个列表(每个处理器一个)并对其执行操作。如果任一进程因Function()而得到“True”,我希望两个进程都终止并返回true。

是否会拆分列表并同时处理每个列表?这样做会有足够的性能奖励吗?如果我选择实施这个问题,可能会遇到哪些问题?

我不确定Function()是否会导致并行性问题,但它所做的只是遍历矩阵m并将其与另一个矩阵进行比较。如果满足它所寻找的条件,则返回true。

2 个答案:

答案 0 :(得分:4)

只要Function()方法本身不会产生太多的争用(资源锁定) - 从你的描述中听起来并不像,并且功能方法(在资源中)的费用足够大(基本上是分配列表,创建额外线程等的开销 - 所以你的收益必须摊销这个成本)然后是。

c#有一些内置的方法来处理这样的情况,你可以使用PLINQ

var y = matricesList.AsParallel().Where(m =>Function(m)).First();

(这将评估列表中的每个项目并返回匹配的第一个值) - 所以如果存在您想要的评估副作用,那么这就是您想要的

如果你希望PLINQ在击中一场比赛后中止,你只需在

中添加.Take(1)
var y = matricesList.AsParallel().Where(m =>Function(m)).Take(1).First();

或任务并行库

    Parallel.ForEach(matricesList, (m, parallelLoopState) =>
                            {
                                if (Function(m))
                                {
                                    parallelLoopState.Stop();
                                }
                            });

这将导致列表中的每个项目被评估,直到Function(m)返回true,然后中止并停止评估其他项目。

两种方法都将处理正确的分区,使用正确数量的线程来处理系统上的处理器数量等。

答案 1 :(得分:2)

如果你纯粹是CPU限制的(即没有不相关的成本,我们不知道可能无法线性扩展的磁盘/网络IO),如果每个测试都是独立的(没有锁冲突),那么漂亮 - 是的,这会有所帮助。它很少完全线性(由于开销),但足够接近。如果您在Web服务器上,您可能希望保持相当保留,因为它已经是高度线程化的,但如果您拥有整个计算机,请使用您拥有的所有核心!实际上,如果你不想让代码痛苦,Parallel.ForEach等会为你做这一切。

我们已经在stackoverflow站点上成功使用了这样的技巧,虽然因为t是一个web服务器,我们将并行性限制为每个请求2个线程,整齐地将时间减半。在以后的情况下,由于需要结合后使用更多踏板的结果实际上适得其反 - 2是我们的甜蜜点。如果您不需要以任何巧妙的方式组合结果,您可以稍微提高并行度。