.NET 实现并行的几种方式(三)
2018-06-22 04:36:31来源:未知 阅读 ()
本随笔续接:.NET 实现并行的几种方式(二)
在前两篇随笔中,先后介绍了 Thread 、ThreadPool 、IAsyncResult (即 APM系列) 、Task 、TPL (Task Parallel Library)。
写到这些笔者突然意识到 还有一个EMP系列没有写,在这里补充一下:
六、 EAP 、EAP中的典型代表是 WebClient:
EAP系列采用 ***Async方法 + ***Completed事件 的编码规范,不做太多解释、具体的demo如下:
var address = "http://www.cnblogs.com/08shiyan/"; WebClient client = new WebClient(); Uri uri = new Uri(address); client.DownloadStringCompleted += new DownloadStringCompletedEventHandler((object sender, DownloadStringCompletedEventArgs e) => { this.txtTip.SetTip("下载完成"); }); client.DownloadStringAsync(uri); this.txtTip.SetTip("开始异步下载数据");
七、PLINQ 、LINQ的并行版本
1) 首先看一下PLINQ在 MSDN 中的介绍 :
并行 LINQ (PLINQ) 是 LINQ 模式的并行实现。 PLINQ 查询在许多方面类似于非并行 LINQ to Objects 查询。 与顺序 LINQ 查询一样,PLINQ 查询对任何内存中 IEnumerable 或 IEnumerable<T> 数据源进行操作,并推迟执行,这意味着在枚举查询之前不会开始执行这些操作。 主要区别是 PLINQ 尝试充分利用系统中的所有处理器。 它利用所有处理器的方法是,将数据源分成片段,然后在多个处理器上对单独工作线程上的每个片段并行执行查询。 在许多情况下,并行执行意味着查询运行速度显著提高。
通过并行执行,PLINQ 通常只需向数据源添加 AsParallel 查询操作,即可在某些查询类型的旧版代码上获得显著的性能改进。 但是,并行可能引入其自己的复杂性,因此并非所有查询操作在 PLINQ 中都运行得更快。 事实上,并行降低了某些查询的速度。 因此,您应了解诸如排序等问题如何影响并行查询。 有关详细信息,请参阅 Understanding Speedup in PLINQ。
从介绍中、我们可以明确三点:
1、PLINQ是LINQ的并行版本、它拥有和LINQ一样一样强大的基因。
2、PLINQ会尝试充分利用所有处理器、(PLINQ在 MSDN 中的介绍 最多是64个),因此许多情况下PLINQ可以显著提高的并行效率,尤其是CPU密集型计算的并行率。
3、并非所有查询操作在 PLINQ 中都运行得更快。
2)PLINQ与LINQ的无缝连接
PLINQ 的实现基础是 :ParallelQuery<TSource>,LINQ的实现基础是:IEnumerable<TSource>, 当然这里说的都是泛型版本。
如下的两个扩展方法、可轻易实现PLINQ和LINQ间的转化。
public static ParallelQuery<TSource> AsParallel<TSource>(this IEnumerable<TSource> source);
public static IEnumerable<TSource> AsSequential<TSource>(this ParallelQuery<TSource> source);
3)简单Demo
/// <summary> /// PLinq:Linq的并行版本 /// </summary> public void Demo1() { Task.Run(() => { var result = Enumerable.Range(1, 10).AsParallel().Where(e => { SetTip("开始 " + e); SetTip("休眠 " + e); Thread.Sleep(1000); SetTip("结束 " + e); return e > 5; }); SetTip("打印结果"); foreach (var item in result) { SetTip(item.ToString()); } SetTip("并行查询执行完毕"); }); }
4)PLINQ与LINQ的微妙关系
在功能上:PLINQ几乎实现了LINQ的全部功能、且方法名都是一致的。
在时间性能上:PLINQ will always attempt to execute a query at least as fast as the query would run sequentially.
因此、PLINQ在执行查询之前会进行一次“预判”,如果发现了某些情况,当前可能会自动转为顺序执行、即LINQ模式。
5)当查询包含以下情况时,PLINQ将会默认按照顺序模式执行
-
包含 Select 子句、已建立索引的 Where 子句、已建立索引的 SelectMany 子句或 ElementAt 子句的查询(在排序或筛选运算符移除或重新排列了索引后)。
-
包含 Take、TakeWhile、Skip、SkipWhile 运算符并且源序列中的索引未采用原始顺序的查询。
-
包含 Zip 或 SequenceEquals 的查询,除非其中一个数据源具有按原始顺序排列的索引,并且另一个数据源可建立索引 (例如:数组 或 IList(T)).
-
包含 Concat 的查询,除非将其应用到可建立索引的数据源。
-
包含 Reverse 的查询,除非应用到可建立索引的数据源。
6) 强制PLINQ并行查询
我们可以通过 WithExecutionMode<TSource> 运算符,指定 ParallelExecutionMode.ForceParallelism 强制PLINQ并行查询。
7)ForAll 多线程枚举
你有可能对“多线程枚举”这个词感到莫名其妙,先看图:
如果你用 foreach、即 IEnumerable 接口枚举并行查询结果,其流程图如第一个所示:即多个线程并行完成后,
还会有一个Merger操作,使结果回到使用该数据的主线程、并将数据合并。
而 ForAll是并行版本的Foreach.
8)其他运算符
1、AsOrdered<TSource> PLINQ查询默认是不保留顺序的。该运算符可保留源序列的顺序(会产生额外的排序开销、降低性能)。
2、AsUnordered<TSource> 是 AsOrdered<TSource>的反操作、对后续操作不在保持序列,可用于中间查询、提高性能。
AsUnordered can be called anywhere in the query; it does not need to be called immediately after AsParallel.
3、WithCancellation<TSource> 用于取消操作
4、WithDegreeOfParallelism<TSource> 用以指定最大可使用的处理器数量。
9)补充:影响PLINQ查询性能的因素
附,Demo : http://files.cnblogs.com/files/08shiyan/ParallelDemo.zip
参见更多:随笔导读:同步与异步
(未完待续...)
标签:
版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有
上一篇:Asp_基础之C#基础
- PHP写UltraEdit插件脚本实现方法 2020-03-29
- PHP实现的MD5结合RSA签名算法实例 2020-03-22
- 利用PHP实现开心消消乐的算法示例 2020-03-22
- PHP基于自定义函数实现的汉字转拼音功能实例 2020-03-17
- PHP实现的基于单向链表解决约瑟夫环问题示例 2020-03-17
IDC资讯: 主机资讯 注册资讯 托管资讯 vps资讯 网站建设
网站运营: 建站经验 策划盈利 搜索优化 网站推广 免费资源
网络编程: Asp.Net编程 Asp编程 Php编程 Xml编程 Access Mssql Mysql 其它
服务器技术: Web服务器 Ftp服务器 Mail服务器 Dns服务器 安全防护
软件技巧: 其它软件 Word Excel Powerpoint Ghost Vista QQ空间 QQ FlashGet 迅雷
网页制作: FrontPages Dreamweaver Javascript css photoshop fireworks Flash