命令式数据并行

    Visual C# 2010和.NETFramework4.0提供了很多令人激动的新特性,这些特性是为应对多核处理器和多处理器的复杂性设计的。然而,因为他们包括了完整的新的特性,开发人员和架构师必须学习一种新的编程模型。

这一章是一些新的类、结构体和枚举类型,你可以使用这里来处理数据并行的场景。这章将为你展示怎样创建并行代码和描述与每个场景相关的新概念,而不是关注并发编程中的最复杂的问题。这样你将可以更加充分的理解性能改进。

开始并行任务

   使用先前版本的.NET Framework,开发可以充分利用多核微处理器的并行能力的应用程序是很难的。使用那些可以控制并行的复杂结构来开始、控制、管理和同步多线程是必要的,但是这对现代的多核系统并不十分有效。

.NET 4引入了新的任务并行库(TPL),其产生在多核时代并且就是第一章中展示的轻量级并发编程模型。

为了支持数据并行、任务并行和管道,TPL提供了一个轻量级的框架,可以帮助开发人员应对不同的并行场景,实现基于任务模型的设计,而不是使用重量级复杂的线程进行工作。这些场景包括

数据并行

  这里有很多的数据,并且每条数据都必须施加相同的操作。如图2-1,使用256位键的AES算法加密100个unicode字符串。

图 2-1

任务并行

      这里有很多不同的操作可以并行执行,充分的利用并行的有力。例如,产生文件的哈希编码,加密unicode字符串,创建图片的缩略图。如图2-2,

图 2-2

   流水线

   这里混杂了任务并行和数据并行。这是最复杂的场景,因为它总是需要协调多个特定的并发任务。例如,以使用256位键的AES算法加密100个unicode字符串,然后为每个加密的字符串产生一个哈希值。这个管道可以实现同时运行两个并发执行加密和产生哈希代码两个任务。每一个加密的unicode字符串为了使用哈希编码算法进行处理而放入队列中。如图2-3,

图 2-3

  当然也存在混合了前边的所有情况的复杂场景。理解怎样使用并行任务进行工作的最容易的方式就是使用他们。接下来的章节将会使用详细的例子覆盖这些最普遍的场景。

  TPL引入了一个新的命名空间,System.Threading.Tasks。通过这个命名空间可以访问.NET4引入的新的类、结构体、枚举类型。所以,无论什么时候你想用TPL,使用这个命名空间是个不错的主意。

  Using System.Threading.Tasks;

这样你可以避免大量的引用。例如,你可以使用Parallel.Invoke,而不是使用System.Threading.Tasks.Parallel.Invoke.

其中主要的类是Task,它代表一个异步的并发操作。然而,没有必要为了创建并行代码直接使用Task的实例。有时,最好的选择是创建并行的循环和区域。在这些场景中,你可以使用静态类Parallel提供的方法进行工作,而不是使用更底层的Task实例。

  • Parallel.For---为固定数目的独立For循环迭代提供负载均衡的潜在的并行执行。

  • Parallel.ForEach---为固定数目的独立For Each循环迭代提供负载均衡的潜在的并行执行。这种方法支持自定义分区类,这是你可以完全控制数据的分布。

  • Parallel.Invok---对独立的任务提供潜在的并行执行。

负载均衡的执行会尝试将工作分发在不同的任务中,这样所有的任务在大部分的时间内都可以保持繁忙。负载均衡总是试图减少任务的闲置时间。

    当重构已经存在的代码来充分利用潜在的并发优势时,这些方法是很有用的。然而,理解这些并不是使用Parallel.For取代for那样简单是很重要的。

Parallel.Invoke

  如果试图将很多方法并行执行最简单的方法就是使用Parallel提供的Invoke方法。以下是.NET中Parallel的Invoke函数原型。Invoke接受没有返回值(或者说返回值是void)Action[]参数数组,对操作尽可能的并行化。

public static void Invoke(params Action[] actions);
/// <summary>
/// 执行所提供的每个操作,而且尽可能并行运行,除非用户取消了操作。
/// </summary>

  有以下四个函数:

        static void First()
{
System.Console.WriteLine("1--First");
} static void Second()
{
System.Console.WriteLine("2--Second");
} static void Third()
{
System.Console.WriteLine("3--Third");
} static void Fourth()
{
System.Console.WriteLine("4--Fourth");
}

使用Parallel的Invoke函数,并行执行以上四个函数。

     Parallel.Invoke(
() => First(),
() => Second(),
() => Third(),
() => Fourth());

  以上调用()=>First()的形式是Lambda表达式。也可以使用匿名委托来执行以上代码,如下代码所示。

     Parallel.Invoke(
delegate { First(); },
delegate { Second(); },
delegate { Third(); },
delegate { Fourth(); });

  或者直接传入函数参数,如下代码所示,但是使用Lambda表达式和匿名委托的一大优势:可以定义需要并行执行的多行方法,而不需要创建额外的方法。

      Parallel.Invoke(
First,
Second,
Third,
Fourth);

    输出结果是:

  第一次执行:3-1-2-4

  第二次执行:1-2-3-4

  第三次执行:2-3-4-1

  使用Parallel的Invoke函数时需要特别注意以下量两点:1、函数执行不要求特定的顺序。2、函数执行必须独立的,不存在特定的依赖关系。

  优势和权衡

  使用Parallel.Invoke的关键优势在于,这是运行并行方法的简单方式,而不用考虑任务和线程问题。然而Invoke并不适合所有情形。需要权衡一下几个方面:

  •   如果使用Parallel.Invoke加载的方法运行时间不同,那么就需要很长的时间才能返回控制。这样很多逻辑内核就处于闲置状态。因此,使用时,一定要测量运行的结果、实现的加速比,以及逻辑内核的使用率,这是很重要的。

  •   在并行的可扩展方面具有局限性。因为Parallel.Invoke调用的是固定数目的委托。

  •   每次调用Parallel.Invoke都要产生一些额外开销。

  •   与其他的并行代码一样,不同方法的任何相关性或不可控的交互会导致难以检测的bug以及意想不到的副作用。

  •   对方法的执行顺序没有要求时,可以考虑Parallel.Invoke方法。需要特定执行顺序的复杂算法不适合使用parallel.Invoke

  •   使用parallel.Invoke并行运行方法中,要考虑异常处理问题。

                                                      参考:无风听海命令式数据并行

                                                          《C#并行编程高级教程》

C#并行编程--命令式数据并行(Parallel.Invoke)的更多相关文章

  1. C#并行编程--命令式数据并行(Parallel.Invoke)---与匿名函数一起理解(转载整理)

    命令式数据并行   Visual C# 2010和.NETFramework4.0提供了很多令人激动的新特性,这些特性是为应对多核处理器和多处理器的复杂性设计的.然而,因为他们包括了完整的新的特性,开 ...

  2. C#并行编程之数据并行

    所谓的数据并行的条件是: 1.拥有大量的数据. 2.对数据的逻辑操作都是一致的. 3.数据之间没有顺序依赖. 运行并行编程可以充分的利用现在多核计算机的优势.记录代码如下: public class ...

  3. 并行编程多线程之Parallel

    1.简介 随着多核时代的到来,并行开发越来越展示出它的强大威力!使用并行程序,充分的利用系统资源,提高程序的性能.在.net 4.0中,微软给我们提供了一个新的命名空间:System.Threadin ...

  4. 五 浅谈CPU 并行编程和 GPU 并行编程的区别

    前言 CPU 的并行编程技术,也是高性能计算中的热点,也是今后要努力学习的方向.那么它和 GPU 并行编程有何区别呢? 本文将做出详细的对比,分析各自的特点,为将来深入学习 CPU 并行编程技术打下铺 ...

  5. 第五篇:浅谈CPU 并行编程和 GPU 并行编程的区别

    前言 CPU 的并行编程技术,也是高性能计算中的热点,也是今后要努力学习的方向.那么它和 GPU 并行编程有何区别呢? 本文将做出详细的对比,分析各自的特点,为将来深入学习 CPU 并行编程技术打下铺 ...

  6. C#并发编程之初识并行编程

    写在前面 之前微信公众号里有一位叫sara的朋友建议我写一下Parallel的相关内容,因为手中商城的重构工作量较大,一时之间无法抽出时间.近日,这套系统已有阶段性成果,所以准备写一下Parallel ...

  7. 一、并行编程 - 数据并行 System.Threading.Tasks.Parallel 类

    一.并行概念 1.并行编程 在.NET 4中的并行编程是依赖Task Parallel Library(后面简称为TPL) 实现的.在TPL中,最基本的执行单元是task(中文可以理解为"任 ...

  8. 【读书笔记】.Net并行编程高级教程--Parallel

    一直觉得自己对并发了解不够深入,特别是看了<代码整洁之道>觉得自己有必要好好学学并发编程,因为性能也是衡量代码整洁的一大标准.而且在<失控>这本书中也多次提到并发,不管是计算机 ...

  9. C#并行编程-Parallel

    菜鸟学习并行编程,参考<C#并行编程高级教程.PDF>,如有错误,欢迎指正. 目录 C#并行编程-相关概念 C#并行编程-Parallel C#并行编程-Task C#并行编程-并发集合 ...

随机推荐

  1. solr笔记之solr下载及安装

    在学习solr过程中,磕磕碰碰,遇到过许多问题,所以特写下笔记,以供需要的时候时常翻阅,也给能看到该博文的博友提供一个不全面的参考. 一.solr简介: Solr是一个独立的企业及搜索应用服务器,它对 ...

  2. 走进 Redis 的世界

    NoSQL(Not Only SQL) 在现今已经应用非常普遍了,尤其是 Redis 和 MongoDB.我们现在来说说 Redis. 前世 Redis 是一个意大利人 Salvatore Sanfi ...

  3. wemall app商城源码中基于JAVA通过Http请求获取json字符串的代码

    wemall-mobile是基于WeMall的Android app商城,只需要在原商城目录下上传接口文件即可完成服务端的配置,客户端可定制修改.分享其中关于通过Http请求获取json字符串的代码供 ...

  4. swift -- 集合

    swift -- 集合 //注意:集合中的元素是无序的,并且不想数组,字典那样,没有索引和键. 1.创建一个空集合 var set1 : Set<Int> = Set<Int> ...

  5. 基于Spring-WS的Restful API的集成测试

    在很多Java企业级应用中,Spring占据了非常重要的位置,这就导致了基本上的技术选型都是围绕着Spring来, 比方说笔者最近的项目需要开发一个Restful的API接口,选型的时候就说,客户架构 ...

  6. js页面跳转常用的几种方式

    第一种: <script language="javascript" type="text/javascript"> window.location ...

  7. win10环境下jdk1.8+Android Developer Tools Build: v22.3.0-887826的问题

    最进换了新电脑,配置开发环境,最新的android studio 要求jdk1.8,所以想都没想就下载1.8. 之后为了一个原来的老项目,得使用adt,遂装之,遇到一下问题 1.ADT新建项目src下 ...

  8. 【iOS】7.4 定位服务->2.1.2 定位 - 官方框架CoreLocation: CLLocationManager(位置管理器)

    本文并非最终版本,如果想要关注更新或更正的内容请关注文集,联系方式详见文末,如有疏忽和遗漏,欢迎指正. 本文相关目录: ================== 所属文集:[iOS]07 设备工具 === ...

  9. Shell中的算术运算(译)

    算术运算 尽管Shell中的变量被缺省地看做是string类型,而非number,但是Shell本身仍然支持算术运算.主要有以下5种方式. 1. declare 2. expr $ z=5 $ z=` ...

  10. hibernate 三种状态的转换

    一.遇到的神奇的事情 使用jpa操作数据库,当我使用findAll()方法查处一个List的对象后,给对这个list的实体进行了一些操作,并没有调用update 或者 saveOrUpdate方法,更 ...