并行聚合集合

时间:2015-11-09 16:01:34

标签: c# parallel-processing aggregate parallel.foreach

我见过基本类型的并行聚合代码,例如

$( 'nav ul li a.active' ).removeClass('active');

我想知道是否有一个列表/其他集合的等价物,例如:

Parallel.For<int>(0, result.Count, () => 0, (i, loop, subtotal) =>
    {
        subtotal += result[i];
        return subtotal;
    },
    (x) => Interlocked.Add(ref sum, x)
);

我猜我没有什么好看又整洁,但我想不出另一种做法,当然不是通过标准的parralel.ForEach因为我不能想到你会怎么说“这个核心有这个范围,这个核心这个范围“....

3 个答案:

答案 0 :(得分:5)

我认为在这两个示例中,PLINQ可以更好地为您服务,而无需在使用非线程安全集合时手动锁定。

您的总和计算可以转换为:

var sum = result.AsParallel().Sum();

您可以将List<T>的第二个示例转换为:

List<Result> results = allIDs.AsParallel()
                             .Select(id => GetResultFor(id))
                             .ToList();

注意并行性与测试所说的一样好。并不总是会并行加速你的代码,有时它甚至可能会降低顺序循环的性能。

答案 1 :(得分:1)

List<Result> AllResults = new List<Result>();

Parallel.ForEach(allIDs, () => new List<Result>(), (id, loopState, subList) =>
{
   subList.Add(GetResultFor(id));
   return subList;
},
subList => 
{ 
     lock(AllResults)
         AllResults.AddRange(subList); 
});

答案 2 :(得分:1)

    var nums = Enumerable.Range(0, 1000000000);
    var parallel = nums.AsParallel();
    var mapped = parallel.Select(x => (long) unchecked( x * x)); 
    var sum = mapped.Sum();

    Console.WriteLine(sum);

映射(Select)总是可以并行发生... reduce(Sum)也是“排序”......你可以使用很多工作线程来汇总所有各种总和,直到你留下“最后一个“总和。通常(90%)将所有内容同步相加可以得到最好的结果。

选择多个的另一个例子:

        IList<IEnumerable<long>> manyNumbers = new List<IEnumerable<long>>();
        for (int i = 0; i < 16; i+=2)
        {
            manyNumbers.Add(Enumerable.Range(2 << i, 2 << (i + 1)).AsParallel().Select(a=> (long)a));
        }
        var parallel = manyNumbers.AsParallel();

        var allPrimes = parallel.SelectMany(sumNums =>
        {
            IEnumerable<long> somePrimes= sumNums.Where(num =>
           {
               for (long i = 2; i <= Math.Sqrt(num); i++)
               {
                   if (num % i == 0)
                   {
                       return false;
                   }
               }
               return true;
           }
            );
            return somePrimes;
        }

        );

        foreach (var number in allPrimes)
        {
            Console.WriteLine(number);
        }

        long sumOfPrimes = allPrimes.Sum();


        Console.WriteLine(sumOfPrimes);
        Console.ReadLine();

这不是一个很好的算法...