惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
云风的 BLOG
云风的 BLOG
美团技术团队
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
爱范儿
爱范儿
Stack Overflow Blog
Stack Overflow Blog
WordPress大学
WordPress大学
GbyAI
GbyAI
雷峰网
雷峰网
P
Proofpoint News Feed
IT之家
IT之家
人人都是产品经理
人人都是产品经理
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
aimingoo的专栏
aimingoo的专栏
小众软件
小众软件
T
The Blog of Author Tim Ferriss
月光博客
月光博客
V
Visual Studio Blog
L
LINUX DO - 热门话题
L
Lohrmann on Cybersecurity
T
Troy Hunt's Blog
Project Zero
Project Zero
U
Unit 42
T
Tor Project blog
Scott Helme
Scott Helme
L
LINUX DO - 最新话题
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
I
InfoQ
Cloudbric
Cloudbric
P
Proofpoint News Feed
The Cloudflare Blog
H
Heimdal Security Blog
Google DeepMind News
Google DeepMind News
The GitHub Blog
The GitHub Blog
Attack and Defense Labs
Attack and Defense Labs
有赞技术团队
有赞技术团队
T
Threat Research - Cisco Blogs
T
The Exploit Database - CXSecurity.com
J
Java Code Geeks
博客园 - 【当耐特】
Security Latest
Security Latest
The Register - Security
The Register - Security
F
Fortinet All Blogs
I
Intezer
H
Hackread – Cybersecurity News, Data Breaches, AI and More
MongoDB | Blog
MongoDB | Blog
N
Netflix TechBlog - Medium
NISL@THU
NISL@THU
T
Tenable Blog

博客园 - ♂风车车

X509Certificate类解析证书的差异,算是.Net的BUG吗? Ninject 2.x细说---2.绑定和作用域 Ninject 2.x细说---1.基本使用 ASP.NET MVC3---1.入门 删除Windows 7系统保留分区100MB .Net并行编程系列文章导航 Entity Framework系列文章导航 多核时代 .NET Framework 4 中的并行编程9---线程安全集合类 多核时代 .NET Framework 4 中的并行编程8---任务的同步 多核时代 .NET Framework 4 中的并行编程7---任务工厂和任务计划 多核时代 .NET Framework 4 中的并行编程5---并行循环Parallel Loop 多核时代 .NET Framework 4 中的并行编程4---异常处理 多核时代 .NET Framework 4 中的并行编程3---任务并行库之Task (下) 多核时代 .NET Framework 4 中的并行编程2---任务并行库之Task (上) 多核时代 .NET Framework 4 中的并行编程1---概述 Entity Framework 4中删除所有数据行的几种方法 ADSL Modern+无线路由实现无线上网 ASP.Net4中实现自定义的请求验证 通过代码理解Asp.net4中的几种ClientIDMode设置.
多核时代 .NET Framework 4 中的并行编程6---并行LINQ
♂风车车 · 2011-09-01 · via 博客园 - ♂风车车

1. 并行LINQ(PLINQ)

并行 LINQ (PLINQ) 是 LINQ 模式的并行实现。 PLINQ 查询在许多方面类似于非并行 LINQ to Objects 查询。 PLINQ 尝试充分利用系统中的所有处理器, 它利用所有处理器的方法是,将数据源分成片段,然后在多个处理器上对单独工作线程上的每个片段并行执行查询。 在许多情况下,并行执行意味着查询运行速度显著提高。

PLINQ有两个重要的类:ParallelEnumerable和ParallelQuery.其中, ParallelEnumerable包含许多在ParallelQuery类型上进行操作的扩展方法. ParallelEnumerable同样实现许多在上Enumerable的方法,因为 ParallelQuery 实现IEnumerable接口,使用我们可以很方便的创建ParallelQuery类的一个实例并运用在ParallelEnumerable上实现的并行方法.接下来,通过代码来学习这些重要的类.

 2. ParallelEnumerable 运算符

ParallelEnumerable包含很多运算符,他们对下封装很多复杂的实现过程, 以便对上我们可以方便的使用并行linq查询.具体如下:

(1) AsParallel

 PLINQ 的入口点。指定如果可能,应并行化查询的其余部分。PLINQ 通常只需向数据源添加 AsParallel 查询操作,即可在某些查询类型的旧版代码上获得显著的性能改进。代码如下:

int[] source = new int[1000];

            for (int i = 0; i < source.Length; i++)

            {

                source[i] = i;

            }

 var  presult = source.AsParallel().Select(c => Math.Pow(c, 3));

            foreach (var d in presult)

            {

                Console.WriteLine("AsParallel Result  is:{0}", d);

            }

通过上面的代码,我们可以通过使用AsParallel()扩展方法,即可开启并行查询.因此,一般的linq查询代码我们只需要使用AsParallel()扩展的方法,即可启用并行查询.

(2) AsSequential<TSource>

 指定查询按顺序运行,也就是将并行的查询转换成一般的顺序查询.代码如下:

            int[] source = new int[1000];

            for (int i = 0; i < source.Length; i++)

            {

                source[i] = i;

            }

            var result = source.AsParallel().AsSequential().Where(c => c > 0);

            foreach (var d in result)

            {

                Console.WriteLine("AsSequential Result:{0}", d);

            }

(3) AsOrdered

 指定 PLINQ 应保留查询的其余部分的源序列排序,直到例如通过使用 orderby子句更改排序为止。但是,因为并行查询的情况,默认未排序的,除非顺序特别重要,否则从性能角度的考虑建议不要排序.

            int[] sourceData = new int[5];

            for (int i = 0; i < sourceData.Length; i++)

            {

                sourceData[i] = i;

            }

            var results1 = sourceData.AsParallel().AsOrdered().Select(c => Math.Pow(c, 3));

            foreach (double d in results1)

            {

                Console.WriteLine("AsOrdered result {0} ", d);

            }

(4) AsUnordered<TSource>

 指定查询的其余部分的 PLINQ 不需要保留源序列的排序。

(5)  WithCancellation<TSource>

 指定 PLINQ 应定期监视请求取消时提供的取消标记和取消执行的状态,这样我们就可以在需要时候取消查询。代码如下:

            CancellationTokenSource token = new CancellationTokenSource();

             int[] sourceData = new int[1000000];

            for (int i = 0; i < sourceData.Length; i++)

            {

                sourceData[i] = i;

            }

            var results1 = sourceData.AsParallel().WithCancellation(token.Token).WithMergeOptions(ParallelMergeOptions.NotBuffered).Where(c => c > 1);

            Task.Factory.StartNew(() =>

            {

                Thread.Sleep(5000);

                token.Cancel();

                Console.WriteLine("Token source cancelled");

            });

            try

            {

                foreach (double d in results1)

                {

                    Console.WriteLine("CancellationTokenSource result {0},Thread Id:{1} ", d, Thread.CurrentThread.ManagedThreadId);

                }

            }

            catch (OperationCanceledException)

            {

                Console.WriteLine("Caught cancellation exception");

            }

            Console.WriteLine("Press enter to finish");

            Console.ReadLine();

(6) WithDegreeOfParallelism<TSource>

 指定 PLINQ 应当用来并行化查询的处理器的最大数目。并行度是将用于处理查询的同时执行的任务的最大数目. 代码如下:

  var results1 = sourceData.AsParallel().WithDegreeOfParallelism(3).Where(c => c > 1);

    我们不防想想,如果将WithDegreeOfParallelism设置为1,会是什么情况呢?

(7) WithMergeOptions<TSource>

 提供有关 PLINQ 应当如何(如果可能)将并行结果合并回到使用线程上的一个序列的提示, 指定查询对输出进行缓冲处理的方式.

   var results1 = sourceData.AsParallel().WithMergeOptions(ParallelMergeOptions.NotBuffered).Where(c => c > 1);

其中ParallelMergeOptions枚举可选择以下几个值:

Ø Default 使用默认合并类型,即 AutoBuffered。 

Ø NotBuffered 不利用输出缓冲区进行合并。一旦计算出结果元素,就向查询使用者提供这些元素。 

Ø AutoBuffered 利用系统选定大小的输出缓冲区进行合并。 在向查询使用者提供结果之前,会先将结果累计到输出缓冲区中。 

Ø FullyBuffered 利用整个输出缓冲区进行合并。 在向查询使用者提供任何结果之前,系统会先累计所有结果。 

(8) WithExecutionMode<TSource>

 指定 PLINQ 应当如何并行化查询(即使默认行为是按顺序运行查询)。

var results1 = sourceData.AsParallel().WithExecutionMode(ParallelExecutionMode.Default).Where(c => c > 1);

 其中, ParallelExecutionMode枚举可以选择如下两种值:

Ø Default 这是默认设置。 PLINQ 将检查查询的结构,仅在可能带来加速时才对查询进行并行化。 如果查询结构指示不可能获得加速,则 PLINQ 会将查询当作普通的 LINQ to Objects 查询来执行。 

Ø ForceParallelism 并行化整个查询,即使要使用系统开销大的算法。 如果认为并行执行查询将带来加速,则使用此标志,但处于默认模式的 PLINQ 将按顺序执行它。 

(9) ForAll<TSource>

 多线程枚举方法,与循环访问查询结果不同,它允许在不首先合并回到使用者线程的情况下并行处理结果。这是处理并行化查询输出的高效方法,因为它不需要在结束时执行合并步骤.代码如下:

  int[] sourceData = new int[5];

            for (int i = 0; i < sourceData.Length; i++)

            {

                sourceData[i] = i;

            }

            sourceData.AsParallel().ForAll((d) =>

            {

                Console.WriteLine("ForAll result {0} ", d);

            }

(10) Aggregate 重载

 对于 PLINQ 唯一的重载,它启用对线程本地分区的中间聚合以及一个用于合并所有分区结果的最终聚合函数。

3. 延迟执行

默认情况下PLINQ和LINQ类似,它只在需要查询结果时才计算.为了快速得到结果,我们可以在查询之后再调用ToArray(), ToDictionary(),ToList()方法,以便使其立刻计算.

4. 异常处理

异常的处理还是使用AggregateException类处理.具体内容可以查看之前的”异常处理”章节.

5. Range方法

ParallelEnumerable类还提供了Rang扩展方法. 它可生成指定范围内的整数的并行序列,也就是在指定的范围内进行并行处理.代码如下:

var result1 =

            from e in ParallelEnumerable.Range(0, 100)

            where e % 2 == 0

            select Math.Pow(e, 2);

6. Repeat方法

ParallelEnumerable类还提供了Repeat扩展方法. 生成包含一个重复值的并行序列,也就是并行生成重复值.代码如下:

var result2 =

            ParallelEnumerable.Repeat(10, 1000)

            .Select(item => Math.Pow(item, 2));

此次,有关PLINQ的基本操作介绍完毕,后续还有其他内容继续介绍.