想要:求和x和求和x * x。其中x = line [i]。
因为有多个线程想要读/写“ sumAll”和“ sumAllQ”,所以我需要锁定其访问权限。
问题在于,这种锁定会在这里序列化事物。我将需要在#“ Environment.ProcessorCount”中拆分此操作以进行循环,每个循环求和数组的一部分,最后求和结果。但是,我该如何以编程方式制作它?
样例代码:
//line is a float[]
Parallel.For(0, line.Length,
new ParallelOptions { MaxDegreeOfParallelism = Environment.ProcessorCount },
i =>
{
x = (double)line[i];
lock (sumLocker)
{
sumAll += x;
sumAllQ += x * x;
}
});
编辑1:
Matthew Watson回答基准结果
在家。 CPU核心2 Quad Q9550 @ 2.83 GHz:
Result via Linq: SumAll=49999950000, SumAllQ=3,33332833333439E+15
Result via loop: SumAll=49999950000, SumAllQ=3,33332833333439E+15
Result via partition: SumAll=49999950000, SumAllQ=3,333328333335E+15
Via Linq took: 00:00:02.6983044
Via Loop took: 00:00:00.4811901
Via Partition took: 00:00:00.1595113
工作中。 CPU i7 930 2.8 GHz:
Result via Linq: SumAll=49999950000, SumAllQ=3,33332833333439E+15
Result via loop: SumAll=49999950000, SumAllQ=3,33332833333439E+15
Result via partition: SumAll=49999950000, SumAllQ=3,333328333335E+15
Via Linq took: 00:00:01.5728736
Via Loop took: 00:00:00.3436929
Via Partition took: 00:00:00.0934209
最佳答案
如注释中所建议,您可以在LINQ中使用Aggregate
和AsParallel
完成此操作。例如:
using System.Linq;
//A class to hold the results.
//This can be improved by making it immutable and using a constructor.
public class Result
{
public double SumAll { get; set; }
public double SumAllQ { get; set; }
}
您可以像这样使用LINQ:
var result = line.AsParallel().Aggregate(new Result(), (input, value) => new Result {SumAll = input.SumAll+value, SumAllQ = input.SumAllQ+value*value});
甚至更好:
var pline = line.AsParallel().WithDegreeOfParallelism(Environment.ProcessorCount);
var result = new Result { SumAll = pline.Sum(), SumAllQ = pline.Sum(x => x * x) };
AsParallel
不能直接指定选项,但是您可以使用.WithDegreeOfParallelism()
,.WithExecutionMode()
或.WithMergeOptions()
来提供更多控制权。您甚至可能必须使用WithDegreeOfParallelism
使其与多个线程一起运行。关于c# - 正确的Parallel.For方法来从Array计算数据,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/16821403/