每台计算机上的物理内核数目不一样,在程序并行运行时并不是运用的内核数越多越好。某些情况下根据实际情况动态的配置会达到更好的效果。
ForAll可以看做是 .NetFramework提供的一种提高效率简化编程的一种可选的操作。它本身就是并行的,主要针对的是处理无序的集合。
指定并行度的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 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();
}
}
}
测试结果:
从测试结果上看,并行度不一样程序运行的时间差别还是很明显的。
单独理解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后,输出的字符串并不是顺序的了。