并行的扩展

扩展1.

Parallel的使用:

在Parallel下面有三个常用的方法Invoke,For,ForEach

Parallel.Invoke()方法是最简单,最简洁的将串行的代码并行化.

在这里先说一点,就是Stopwatch的使用,Stopwatch到底是个什么东西,首先Stopwatch在命名空间System.Diagnostics中.

使用方法如下:

var StopWatch =new Stopwatch();//创建一个Stopwatch实例

StopWatch.Start();//开始计时

StopWatch.Stop();//停止计时

StopWatch.Reset();//重置StopWatch

StopWatch.Restart();//重启被停止的Stopwatch

stopWatch.ElapsedMilliseconds //获取stopWatch从开始到现在的时间差,单位是毫秒

案例:

using System;

using System.Collections.Concurrent;

using System.Collections.Generic;

using System.Diagnostics;

using System.Linq;

using System.Text;

using System.Threading;

using System.Threading.Tasks;

namespace 并行集合和LINQ

{

class Program

{

static void Main(string[] args)

{

Custom custom = new Custom();

custom.ParallelInvokeMethod();

Console.WriteLine("运行完成");

Console.ReadKey();

}

}

public class Custom

{

private Stopwatch stopWatch = new Stopwatch();

public void Run1()

{

Thread.Sleep(2000);//Thread需要添加命名空间

Console.WriteLine("Task 1 is cost 2 sec");

}

public void Run2()

{

Thread.Sleep(3000);

Console.WriteLine("Task 2 is cost 3 sec");

}

public void ParallelInvokeMethod()

{

stopWatch.Start();

Parallel.Invoke(Run1, Run2);

stopWatch.Stop();

Console.WriteLine("Parallel run " + stopWatch.ElapsedMilliseconds + " ms.");//这是在并行的情况下

stopWatch.Restart();

Run1();

Run2();

stopWatch.Stop();

Console.WriteLine("Normal run " + stopWatch.ElapsedMilliseconds + " ms.");//这是正常情况

}

}

}

分析:正确情况下确实应该是5秒左右,明明白白写着呢,3000+2000=5000ms,而使用了Parallel.Invoke方法只用了3秒,由此可见并行执行提高了很多效率.

扩展2:Parallel.For

这个方法和For循环的功能类似,案例:

using System;

using System.Collections.Generic;

using System.Diagnostics;

using System.Linq;

using System.Text;

using System.Threading.Tasks;

namespace 并行扩展

{

class Program

{

static void Main(string[] args)

{

Stopwatch stopWatch = new Stopwatch();

stopWatch.Start();

for (int i = 0; i < 10000; i++)

{

for (int j = 0; j < 60000; j++)

{

int sum = 0;

sum += i;

}

}

stopWatch.Stop();

Console.WriteLine("NormalFor run " + stopWatch.ElapsedMilliseconds + " ms.");

stopWatch.Reset();

stopWatch.Start();

Parallel.For(0, 10000, item =>

{

for (int j = 0; j < 60000; j++)

{

int sum = 0;

sum += item;

}

});

stopWatch.Stop();

Console.WriteLine("ParallelFor run " + stopWatch.ElapsedMilliseconds + " ms.");

Console.WriteLine("运行完毕");

Console.ReadKey();

}

}

}

分析:写了两个循环,做些无用的操作,主要是消耗CPU的资源,通过多次运行结果可以看到们使用了Parallel.For所有的时间差不多也就是单纯for时间的三分之一.是不是在任何时候Parallel.For在任何时候都比这普通的for快呢,肯定不是啊,要是这样的话,C#的for早就淘汰了.

案例:修改代码,添加一个全局变量num

using System;

using System.Collections.Concurrent;

using System.Collections.Generic;

using System.Diagnostics;

using System.Linq;

using System.Text;

using System.Threading.Tasks;

namespace 并行扩展

{

class Program

{

static void Main(string[] args)

{

Stopwatch stopWatch = new Stopwatch();

var obj = new Object();

long num = 0;

ConcurrentBag<long> bag = new ConcurrentBag<long>();

stopWatch.Start();

for (int i = 0; i < 10000; i++)

{

for (int j = 0; j < 60000; j++)

{

//int sum = 0;

//sum += item;

num++;

}

}

stopWatch.Stop();

Console.WriteLine("NormalFor run " + stopWatch.ElapsedMilliseconds + " ms.");

stopWatch.Reset();

stopWatch.Start();

Parallel.For(0, 10000, item =>

{

for (int j = 0; j < 60000; j++)

{

//int sum = 0;

//sum += item;

lock (obj)

{

num++;

}

}

});

stopWatch.Stop();

Console.WriteLine("ParallelFor run " + stopWatch.ElapsedMilliseconds + " ms.");

//并行的问题,需要多运行几遍,一遍两遍看不出什么东西来

Console.WriteLine("运行完毕");

Console.ReadKey();

}

}

}

分析:Parallel.For由于是并行运行的,所以会同时访问访问全局变量num,为了得到正确的结果,要使用lock,所以Parallel.For竟然耗了这么多时间,这是因为并行同时访问全局变量,会出现资源争夺(我的电脑当时开着虚拟机,听着音乐,在程序运行的时候我我Ctrl+S了以下文档,我的电脑出现卡死的情况),大不多的资源都消耗在了资源等待上面.

虽然一直说并说,但一直没有证明一下,你肯定不服,来让你服气:

Parallel.For(0, 100, i =>

{

Console.Write(i + "\t");

});

Console.WriteLine("运行完毕");

从0输出到99,运行后会发现输出的顺序不对,用for顺序肯定是对的,并行同时执行,所以会出现输出顺序不同的情况。

扩展3

Parallel.ForEach

这个方法和普通的foreach很相似,案例:

List<int> list = new List<int>();

for (int i = 0; i < 100000; i++)

{

list.Add(i);

}

Stopwatch stopWatch = new Stopwatch();

stopWatch.Start();

Parallel.ForEach(list, i =>

{

i++;

});

stopWatch.Stop();

Console.WriteLine(stopWatch.ElapsedMilliseconds);

Parallel中途退出循环和异常处理

我们为啥使用Parallel呢,肯定是在处理一些比较好使的任务,当然也很消耗CPU资源和内存,如果我们在中途想停止,怎么办呢?

串行好办啊,一个break搞定,但是串行呢?貌似不知道呢,在并行循环的委托参数中提供了一个ParallelLoopState,该实例提供了Break和Stop方法来帮助我们!

Break: 当然这个是通知并行计算尽快的退出循环,比如并行计算正在迭代100,那么break后程序还会迭代所有小于100的。

Stop:这个就不一样了,比如正在迭代100突然遇到stop,那它啥也不管了,直接退出。

案例:

Stopwatch stopWatch = new Stopwatch();

ConcurrentBag<int> bag = new ConcurrentBag<int>();

stopWatch.Start();

Parallel.For(0, 1000, (i, state) =>

{

if (bag.Count == 300)

{

//state.Stop();//也可能会出现300多,但是不会很夸张,在我的测试下,最多出现303,大部分还是300

state.Break();//如果是break的话,可能会看到Bag count is 300(多),在我多次测试下,得到最夸张的结果是840

return;

}

bag.Add(i);

});

stopWatch.Stop();

Console.WriteLine("Bag count is " + bag.Count + ", " + "一共用时 :"+stopWatch.ElapsedMilliseconds+"ms");

Console.WriteLine("运行完毕");

Console.ReadKey();

异常:

首先任务是并行计算的,处理过程中可能会产生n多的异常,那么如何来获取到这些异常呢?普通的Exception并不能获取到异常,然而为并行诞生的AggregateExcepation就可以获取到一组异常。

这里我们修改Parallel.Invoke的代码,修改后代码如下:

private Stopwatch stopWatch = new Stopwatch();

public void Run1()

{

Thread.Sleep(2000);

Console.WriteLine("Task 1 is cost 2 sec");

throw new Exception("Exception in task 1");

}

public void Run2()

{

Thread.Sleep(3000);

Console.WriteLine("Task 2 is cost 3 sec");

throw new Exception("Exception in task 2");

}

public void ParallelInvokeMethod()

{

stopWatch.Start();

try

{

Parallel.Invoke(Run1, Run2);

}

catch (AggregateException aex)

{

foreach (var ex in aex.InnerExceptions)

{

Console.WriteLine(ex.Message);

}

}

stopWatch.Stop();

Console.WriteLine("Parallel run " + stopWatch.ElapsedMilliseconds + " ms.");

stopWatch.Reset();

stopWatch.Start();

try

{

Run1();

Run2();

}

catch (Exception ex)

{

Console.WriteLine(ex.Message);

}

stopWatch.Stop();

Console.WriteLine("Normal run " + stopWatch.ElapsedMilliseconds + " ms.");

Console.WriteLine("运行完毕");

Console.ReadKey();

C#编程(六十四)----------并行扩展的更多相关文章

  1. Gradle 1.12用户指南翻译——第六十四章. 发布到Ivy(新)

    其他章节的翻译请参见:http://blog.csdn.net/column/details/gradle-translation.html翻译项目请关注Github上的地址:https://gith ...

  2. 孤荷凌寒自学python第六十四天学习mongoDB的基本操作并进行简单封装3

    孤荷凌寒自学python第六十四天学习mongoDB的基本操作并进行简单封装3 (完整学习过程屏幕记录视频地址在文末) 今天是学习mongoDB数据库的第十天. 今天继续学习mongoDB的简单操作, ...

  3. SpringBoot进阶教程(六十四)注解大全

    在Spring1.x时代,还没出现注解,需要大量xml配置文件并在内部编写大量bean标签.Java5推出新特性annotation,为spring的更新奠定了基础.从Spring 2.X开始spri ...

  4. 第三百六十四节,Python分布式爬虫打造搜索引擎Scrapy精讲—elasticsearch(搜索引擎)的mapping映射管理

    第三百六十四节,Python分布式爬虫打造搜索引擎Scrapy精讲—elasticsearch(搜索引擎)的mapping映射管理 1.映射(mapping)介绍 映射:创建索引的时候,可以预先定义字 ...

  5. “全栈2019”Java第六十四章:接口与静态方法详解

    难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java第 ...

  6. 学习ASP.NET Core Razor 编程系列十四——文件上传功能(二)

    学习ASP.NET Core Razor 编程系列目录 学习ASP.NET Core Razor 编程系列一 学习ASP.NET Core Razor 编程系列二——添加一个实体 学习ASP.NET ...

  7. OpenCV开发笔记(六十四):红胖子8分钟带你深入了解SURF特征点(图文并茂+浅显易懂+程序源码)

    若该文为原创文章,未经允许不得转载原博主博客地址:https://blog.csdn.net/qq21497936原博主博客导航:https://blog.csdn.net/qq21497936/ar ...

  8. C#高级编程六十九天----DLR简介 .在.NET中使用DLR(转载) 我也来说说Dynamic

    DLR 一.近年来,在TIOBE公司每个月发布的编程语言排行榜中,C#总是能挤进前十名,而在最近十年来,C#总体上呈现上升的趋势.C#能取得这样的成绩,有很多因素,其中它在语言特性上的锐意进取让人印象 ...

  9. 第六十四天 JS基础操作

    一.分支结构 1.if语句 if基础语句 if(条件表达式){ 代码块: } // 当条件表达式结果为true,会执行代码块:反之不执行 // 条件表达式可以为普通表达式 // 0.undefined ...

随机推荐

  1. 【linux】grep的使用

    最近发现了grep一个超级好用的指令 1. 在当前目录及其子目录中查找所有包含字符串abc的文件及位置 grep -rn "abc" * 2. 查找不包含"abc&quo ...

  2. ubuntu eclipse 找不到jre文件

    一. 把jdk下的jre文件copy到eclipse安装目录 二. 打开eclipse 重新设计library和工作空间

  3. python3.6连接oracle数据库

    下载cx_Oracle模块模块: https://pypi.python.org/pypi/cx_Oracle/5.2.1#downloads 这里下载的是源码进行安装 [root@oracle or ...

  4. centos 监控进程,并自动重启

    编辑Crontab crontab -e 按i进行编辑 */ * * * * /root/monitor.sh # 每分钟运行一遍monitor.sh脚本 * * * /sbin/reboot # 每 ...

  5. NOIP2018濒死记

    已经复课常规三个多星期了...终于有时间来写Noip2018游记了.当时的一些想法可能都不记得了...我的OI生涯也时日无多了.也许一开始我的选择就是错的,我之前就这么想,只不过现在更加确信了而已.等 ...

  6. word2vec中的数学原理一 目录和前言

    最近在看词向量了,因为这个概念对于语言模型,nlp都比较重要,要好好的学习一下.把网上的一些资料整合一下,搞个系列. 主要参考:    word2vec 中的数学原理详解                ...

  7. 018 HDFS中,namenode与datanode的交互

    1.解释 2.启动过程 namenode需要等待给他汇报块的情况,然后namenode会给datanode一个反馈. namenode在启动的时候有一个等待的过程. 3.如果有块损坏 等待报告中,na ...

  8. 013.Zabbix的Items(监控项)

    一 Items简介 Items是从主机里面获取的所有数据,可以配置获取监控数据的方式.取值的数据类型.获取数值的间隔.历史数据保存时间.趋势数据保存时间.监控key的分组等. 通常情况下item由ke ...

  9. 【python学习-1】python环境设置与开发

    开始学习python,打算把学习过程都记下来. 下载python,虽然推荐官网,但是感觉官网上面下载python太慢,所以我最后是在csdn上面下载的python版本(3.2.4 windows 64 ...

  10. 求任意多边形面积 python实现

    数学解决方法: 多边形外选取一点,连接各点构成三角形,计算求和......  详细链接  http://blog.csdn.net/hemmingway/article/details/7814494 ...