并行编程之PLINQ
并行编程之PLINQ
并行 LINQ (PLINQ) 是 LINQ 模式的并行实现。PLINQ 的主要用途是通过在多核计算机上以并行方式执行查询委托来加快 LINQ to Objects 查询的执行速度。与顺序 LINQ 查询一样,PLINQ 查询对任何内存中 IEnumerable 或 IEnumerable<(Of <(T>)>) 数据源进行操作,并推迟执行,这意味着在枚举查询之前不会开始执行这些操作。主要区别是 PLINQ 尝试充分利用系统中的所有处理器。它利用所有处理器的方法是,将数据源分成片段,然后在多个处理器上对单独工作线程上的每个片段并行执行查询。在许多情况下,并行执行意味着查询运行速度显著提高。
通过并行执行,PLINQ 通常只需向数据源添加 AsParallel 查询操作,即可在某些查询类型的旧版代码上获得显著的性能改进。但是,并行可能引入其自己的复杂性,因此并非所有查询操作在 PLINQ 中都运行得更快。事实上,并行降低了某些查询的速度。
System.Linq..::.ParallelEnumerable 类公开 PLINQ 的几乎所有功能。此类和 System.Linq 命名空间类型的其余部分一起编译到 System.Core.dll 程序集中。
1、选择使用模型
当您编写查询时,通过在数据源上调用 ParallelEnumerableAsParallel()()() 扩展方法来选择使用 PLINQ,如下面的示例所示。
var source = Enumerable.Range(1, 10000);
// Opt-in to PLINQ with AsParallel
var evenNums = from num in source.AsParallel()
where Compute(num) > 0
select num;
2、并行度
默认情况下,PLINQ 使用主机上的所有处理器,这些处理器的数量最多可达 64 个。通过使用 WithDegreeOfParallelism()()() 方法,可以指示 PLINQ 使用不多于指定数量的处理器。这在当您要确保计算机上运行的其他进程收到一定的 CPU 时间量时非常有用。下面的代码段将查询限制为最多使用两个处理器。
var query = from item in source.AsParallel().WithDegreeOfParallelism(2)
where Compute(item) > 42
select item;
3、总体工作的计算开销
为了实现加速,PLINQ 查询必须具有足够的适合并行工作来弥补开销。工作可表示为每个委托的计算开销与源集合中元素数量的乘积。假定某个操作可并行化,则它的计算开销越高,加速的可能性就越大。例如,如果某个函数执行花费的时间为 1 毫秒,则针对 1000 个元素进行的顺序查询将花费 1 秒来执行该操作,而在四核计算机上进行的并行查询可能只花费 250 毫秒。这样就产生了 750 毫秒的加速。如果该函数对于每个元素需要花费 1 秒来执行,则加速将为 750 秒。如果委托的开销很大,则对于源集合中的很少几个项,PLINQ 可能会提供明显的加速。相反,包含无关紧要委托的小型源集合通常不适合于 PLINQ。
在下面的示例中,queryA 可能适合于 PLINQ(假定其 Select 函数涉及大量工作)。queryB 可能不适合,原因是 Select 语句中没有足够的工作,并且并行化的开销将抵销大部分或全部加速。
var queryA = from num in source.AsParallel()
select ExpensiveFunction(num); //good for PLINQ
var queryB = from num in source.AsParallel()
where num % 2 > 0
select num; //not as good for PLINQ
4、PLINQ 何时选择顺序模式
PLINQ 将始终尝试至少按与查询以顺序方式运行同样的速度来执行查询。尽管 PLINQ 不会查看用户委托的计算开销有多高或输入源有多大,但它却会查找某些查询"形状"。具体而言,它将查找通常会导致查询在并行模式下运行更慢的查询运算符或运算符组合。如果找到此类形状,PLINQ 默认情况下会转而使用顺序模式。
但是,在衡量特定查询的性能后,您可能会确定该查询在并行模式下实际运行更快。在这些情况下,您可以通过 ParallelEnumerableWithExecutionMode()()() 方法使用 ParallelExecutionMode..::.ForceParallelism 标志,以指示 PLINQ 对查询进行并行化。有关更多信息,请参见如何:在 PLINQ 中指定执行模式。
下面的列表介绍了 PLINQ 默认情况下将按顺序模式执行的查询形状:
- 包含 Select 子句、已建立索引的 Where 子句、已建立索引的 SelectMany 子句或 ElementAt 子句的查询(在排序或筛选运算符移除或重新排列了索引后)。
- 包含 Take、TakeWhile、Skip、SkipWhile 运算符并且源序列中的索引未采用原始顺序的查询。
- 包含 Zip 或 SequenceEquals 的查询,除非其中一个数据源具有按原始顺序排列的索引,并且另一个数据源可建立索引(即,数组或 IList(T))。
- 包含 Concat 的查询,除非将其应用到可建立索引的数据源。
- 包含 Reverse 的查询,除非应用到可建立索引的数据源。
5、PLINQ 中的顺序保留
下面的示例演示一个未排序的并行查询,该查询筛选与某个条件匹配的所有元素,而不会尝试以任何方式对结果进行排序。此查询不一定会生成源序列中满足条件的前1000 个城市,而是会生成满足条件的某一组 1000 个城市。您可以通过对源序列使用 AsOrdered()()() 运算符来启用顺序保留。然后,您可以稍后通过使用 AsUnOrdered()()() 方法在查询中禁用顺序保留。
var cityQuery = (from city in cities.AsParallel()
where city.Population > 10000
select city)
.Take(1000);
查询运算符和排序
下面的查询运算符将顺序保留引入查询的所有后续运算中,或直至调用 AsUnordered()()() 为止:
- OrderBy()()()
- OrderByDescending()()()
- ThenBy()()()
- ThenByDescending()()()
下面的 PLINQ 查询运算符在某些情况下可能要求经过排序的源序列生成正确的结果:
- Reverse()()()
- SequenceEquals()()()
- TakeWhile()()()
- SkipWhile()()()
- Zip()()()
并行编程之PLINQ的更多相关文章
- .Net并行编程之二:并行循环
本篇内容主要包括: 1.能够转化为并行循环的条件 2.并行For循环的用法:Parallel.For 3.并行ForEach的用法Parallel.ForEach 4.并行LINQ(PLINQ)的用法 ...
- Pthreads并行编程之spin lock与mutex性能对比分析(转)
POSIX threads(简称Pthreads)是在多核平台上进行并行编程的一套常用的API.线程同步(Thread Synchronization)是并行编程中非常重要的通讯手段,其中最典型的应用 ...
- 并行编程之CountdownEvent的用法
教程:http://blog.gkarch.com/threading/part5.html#the-parallel-class http://www.cnblogs.com/huangxinche ...
- 异步编程之Promise(3):拓展进阶
异步编程系列教程: (翻译)异步编程之Promise(1)--初见魅力 异步编程之Promise(2):探究原理 异步编程之Promise(3):拓展进阶 异步编程之Generator(1)--领略魅 ...
- iOS 多线程编程之Grand Central Dispatch(GCD)
介绍: Grand Central Dispatch 简称(GCD)是苹果公司开发的技术,以优化的应用程序支持多核心处理器和其它的对称多处理系统的系统.这建立在任务并行运行的线程池模式的基础上的. 它 ...
- 深入浅出Cocoa多线程编程之 block 与 dispatch quene
深入浅出 Cocoa 多线程编程之 block 与 dispatch quene 罗朝辉(http://www.cppblog.com/kesalin CC 许可,转载请注明出处 block 是 Ap ...
- python并发编程之multiprocessing进程(二)
python的multiprocessing模块是用来创建多进程的,下面对multiprocessing总结一下使用记录. 系列文章 python并发编程之threading线程(一) python并 ...
- Python函数式编程之map()
Python函数式编程之map() Python中map().filter().reduce()这三个都是应用于序列的内置函数. 格式: map(func, seq1[, seq2,…]) 第一个参数 ...
- [Cocoa]深入浅出Cocoa多线程编程之 block 与 dispatch quene
深入浅出 Cocoa 多线程编程之 block 与 dispatch quene 罗朝辉(http://www.cppblog.com/kesalin CC 许可,转载请注明出处 block 是 Ap ...
随机推荐
- PHP于Post和Get得到的数据写入到文件中
有时Post要么Get越过那我们不知道什么样的形状数据,它可以是JSON格风格或只是简单地通过数据.这一次,我们能够把他写的文字,传过来的数据是什么格式了. $val = ""; ...
- HDU 4123 Bob’s Race 树的直径+单调队列
题意: 给定n个点的带边权树Q个询问. 以下n-1行给出树 以下Q行每行一个数字表示询问. 首先求出dp[N] :dp[i]表示i点距离树上最远点的距离 询问u, 表示求出 dp 数组中最长的连续序列 ...
- Mac OS X中报:java.io.UnixFileSystem.createFileExclusively(Native Method)的简单原因
这个博客太简单了!想到可能有其它朋友也遇到这个问题,就记录一下. 今天把一个之前在Windows上的Java项目放到Mac OS X上执行,本来认为应该非常easy的事情,结果还是报: Excepti ...
- Custom Data Service Providers
Custom Data Service Providers Introduction Data Services sits above a Data Service Provider, which i ...
- DOS call 中的%cd%,当前文件夹演示
最近的工作要处理.bat文件,在dos文件错综复杂的调用过程中,我迷失了,于是%cd% @echo %cd% @cd %cd%\-- @pause @call %cd%\--\1.bat @pause ...
- 并查集(Union-Find)算法介绍
原文链接:http://blog.csdn.net/dm_vincent/article/details/7655764 本文主要介绍解决动态连通性一类问题的一种算法,使用到了一种叫做并查集的数据结构 ...
- 至尊快速,国产语言RPP 1.83强势来袭
以下是 R++的性能測试数据:(奔腾 1.86GHZ,測试 3 次取平均值) 执行效率: R++的内部结构和 C++大致同样,所以理论上 R++能够达到和 C++一样的执行速度,眼下 R++已开启汇编 ...
- C#实现对mongoDB的简单增删查改
首先添加所需要驱动包(可通过nuget获得) using MongoDB.Bson;using MongoDB.Driver;using MongoDB.Driver.Builders; 一.设置配置 ...
- 去除win7 64位系统桌面图标小箭头
http://blog.csdn.net/pipisorry/article/details/24865195 在桌面新建一个文本文档 去除箭头.txt,把例如以下代码粘贴到文档中reg add &q ...
- Cgroup maintainer丽泽范:解剖Linux核心容器技术
摘要:Cgroup和namespace等内核特性如何出现,在社区处于如何的开发状况?Docker如火如荼.内核社区是否会因此加紧完好容器技术的隔离性安全性?华为Linux内核高级project师李泽帆 ...