C# 并行编程 之 PLINQ并行度的指定 和 ForAll的使用

概要

每台计算机上的物理内核数目不一样,在程序并行运行时并不是运用的内核数越多越好。某些情况下根据实际情况动态的配置会达到更好的效果。

ForAll可以看做是 .NetFramework提供的一种提高效率简化编程的一种可选的操作。它本身就是并行的,主要针对的是处理无序的集合。

PLINQ指定并行度

指定并行度的API:WithDegreeOfParallelism(N),并行度并不是越大越好,如果运算时把CPU都占满了,很有可能影响GUI对用户的响应。

示例代码:
代码中指定了不同的并行度,并且对他们的运算时间进行了比较 分别指定为2 和 4。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Diagnostics;

namespace Sample6_5_plinq_withdegreeofparallelism
{
    class Program
    {
        static int NUM_INTS = 500000000;

        static ParallelQuery<int> GenerateInputeData4Parallel()
        {
            return ParallelEnumerable.Range(1, NUM_INTS);
        }

        static void Main(string[] args)
        {
            var palTarget = GenerateInputeData4Parallel();
            Console.WriteLine("============================================================");
            Console.WriteLine("TEST PARALLEL LINQ: Parallelism = 2");
            Console.WriteLine("============================================================");
            var swatchp2 = Stopwatch.StartNew();

            var palQuery = (from intNum in palTarget.AsParallel().WithDegreeOfParallelism(2)
                            where ((intNum % 5) == 0)
                            select (intNum / Math.PI)).Average();
            swatchp2.Stop();

            Console.WriteLine("PLINQ Result: " + palQuery + " LINQ Use Time: {0}", swatchp2.Elapsed);


            palTarget = GenerateInputeData4Parallel();
            Console.WriteLine("\n\n");
            Console.WriteLine("============================================================");
            Console.WriteLine("TEST PARALLEL LINQ: Parallelism = 4");
            Console.WriteLine("============================================================");
            var swatchp4 = Stopwatch.StartNew();

            palQuery = (from intNum in palTarget.AsParallel().WithDegreeOfParallelism(4)
                            where ((intNum % 5) == 0)
                            select (intNum / Math.PI)).Average();
            swatchp4.Stop();

            Console.WriteLine("PLINQ Result: " + palQuery + " LINQ Use Time: {0}", swatchp4.Elapsed);
            Console.ReadLine();
        }
    }
}

测试结果:
从测试结果上看,并行度不一样程序运行的时间差别还是很明显的。

PLINQ ForAll

单独理解ForAll比较麻烦,但用图把它和Foreach放到一起比较一下理解起来就简单了。

在 Foreach 的操作中,隐含的是在汇总每个任务的操作结果时对数据的顺序是有要求的,是按一定顺序进行的。但对于ForAll来说是没有要求的。在操作无序的数据时可以提高一定的效率。

示例代码:
代码很简单,就是找到含有a的字符串,并排序输出,输出以后把字符变为大写,这个操作使用ForAll来执行。

using System;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Diagnostics;
using System.Linq;
using System.IO;
using System.Collections.Concurrent;

namespace Sample6_6_plinq_forall
{
    class Program
    {
        static string[] words = { "Day", "Car", "Land", "Road", "Sea", "Mountain", "River" };

        static void Main(string[] args)
        {
            Console.WriteLine("============================================================");
            Console.WriteLine("Parallel Test Ordered String");
            Console.WriteLine("============================================================");
            var orderwords = from word in words.AsParallel()
                             where (word.Contains('a'))
                             orderby word ascending
                             select word;

            var orderletterList = orderwords.ToList();
            for (int i = 0; i < orderletterList.Count; i++)
            {
                Console.WriteLine(orderletterList[i]);
            }

            Console.WriteLine("\n\n");
            Console.WriteLine("============================================================");
            Console.WriteLine("ForAll Result");
            Console.WriteLine("============================================================");

            ConcurrentBag<string> newForAllData = new ConcurrentBag<string>();
            orderwords.ForAll((e) => newForAllData.Add(e.ToUpper()));
            for (int i = 0; i < newForAllData.Count; i++)
            {
                Console.WriteLine(newForAllData.ElementAt(i));
            }

            Console.ReadLine();
        }
    }
}

从测试结果可以看出,当使用完ForAll后,输出的字符串并不是顺序的了。

你可能感兴趣的:(PLINQ)