.NET并行计算基本介绍、并行循环使用模式)

阅读目录:

  • 1.开篇介绍
  • 2.NET并行计算基本介绍
  • 3.并行循环使用模式
    • 3.1并行For循环
    • 3.2并行ForEach循环
    • 3.3并行LINQ(PLINQ)

1】开篇介绍

最近这几天在捣鼓并行计算,发现还是有很多值得分享的意义,因为我们现在很多人对它的理解还是有点不准确,包括我自己也是这么觉得,所以整理一些文章分享给在使用.NET并行计算的朋友和将要使用.NET并行计算的朋友;

NET并行编程推出已经有一段时间了,在一些项目代码里也时不时会看见一些眼熟的并行计算代码,作为热爱技术的我们怎能视而不见呢,于是捣鼓了一番跟自己的理解恰恰相反,看似一段能提高处理速度的并行代码为能起效果,跟直接使用手动创建的后台线程处理差不多,这不太符合我们对.NET并行的强大技术的理解,所以自己搞了点资料看看,实践了一下,发现在使用.NET并行技术的时候需要注意一些细节,这些细节看代码是看不出来的,所以我们看到别人这么用我们就模仿这么用,我们需要自己去验证一下到底能提高多少处理速度和它的优势在哪里;要不然效率上不去反而还低下,查看代码也不能很好的断定哪里出了问题,所以还是需要系统的学习总结才行;

现在的系统已经不在是以前桌面程序了,也不是简单的WEB应用系统,而是大型的互联网社区、电子商务等大型系统,具有高并发,大数据、SOA这些相关特性的复杂体系的综合性开放平台;.NET作为市场占有率这么高的开发技术,有了一个很强大的并行处理技术,目的就是为了能在高并发的情况下提高处理效率,提高了单个并发的处理效率也就提高了总体的系统的吞吐量和并发数量,在单位时间内处理的数据量将提高不是一个系数两个系数;一个处理我们提高了两倍到三倍的时间,那么在并发1000万的顶峰时时不时很客观;

2】.NET并行计算基本介绍

既然是.NET并行计算,那么我们首先要弄清楚什么叫并行计算,与我们以前手动创建多线程的并行计算有何不同,好处在哪里;我们先来了解一下什么是并行计算,其实简单形容就是将一个大的任务分解成多个小任务,然后让这些小任务同时的进行处理,当然纯属自己个人理解,当然不是很全面,但是我们使用者来说足够了;

在以前单个CPU的情况下只能靠提高CPU的时钟频率,但是毕竟是有极限的,所以现在基本上是多核CPU,个人笔记本都已经基本上是4核了,服务器的话都快上20了;在这样一个有利的计算环境下,我们的程序在处理一个大的任务时为了提高处理速度需要手动的将它分解然后创建Thread来处理,在.NET中我们一般都会自己创建Thread来处理单个子任务,这大家都不陌生,但是我们面临的问题就是不能很好的把握创建Thread的个数和一些参数的控制,毕竟.NET并行也是基于以前的Thread来写的,如何在多线程之间控制参数,如何互斥的执行的线程顺序等等问题,导致我们不能很好的使用Thread,所以这个时候.NET并行框架为我们提供了一个很好的并行开发平台,毕竟大环境就是多核时代;

下面我们将接触.NET并行计算中的第一个使用模式,有很多并行计算场景,归结起来是一系列使用模式;

3】并行循环模式

并行循环模式就是将一个大的循环任务分解成多个同时并行执行的小循环,这个模式很实用;我们大部分处理程序的逻辑都是在循环和判断之间,并行循环模式可以适当的改善我们在操作大量循环逻辑的效率;

我们看一个简单的例子,看到底提升了多少CPU利用率和执行时间;

 
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using System.Diagnostics;
namespace ConsoleApplication1.Data
{
public class DataOperation
{
private static List<Order> orders = new List<Order>();
static DataOperation()
{
for (int i = 0; i < 9000000; i++)
{
orders.Add(new Order() { Oid = Guid.NewGuid().ToString(), OName = "OrderName_" + i.ToString() });
}
}
public void Operation()
{
Console.WriteLine("Please write start keys:");
Console.ReadLine();
Stopwatch watch = new Stopwatch();
watch.Start();
orders.ForEach(order =>
{
order.IsSubmit = true;
int count = 0;
for (int i = 0; i < 2000; i++)
{
count++;
}
});
watch.Stop();
Console.WriteLine(watch.ElapsedMilliseconds);
}
public void TaskOperation()
{
Console.WriteLine("Please write start keys:");
Console.ReadLine();
Stopwatch watch = new Stopwatch();
watch.Start();
Parallel.ForEach(orders, order =>
{
order.IsSubmit = true;
int count = 0;
for (int i = 0; i < 2000; i++)
{
count++;
}
});
watch.Stop();
Console.WriteLine(watch.ElapsedMilliseconds);
}
}
}

这里的代码其实很简单,在静态构造函数中我初始化了九百万条测试数据,其实就是Order类型的实例,这在我们实际应用中也很常见,只不过不是一次性的读取这么多数据而已,但是处理的方式基本上差不多的;然后有两个方法,一个是Operation,一个是TaskOperation,前者顺序执行,后者并行执行;

在循环的内部我加上了一个2000的简单空循环逻辑,为什么要这么做后面会解释介绍(小循环并行模式不会提升性能反而会降低性能);这里是为了让模拟场景更真实一点;

我们来看一下测试相关的数据:i5、4核测试环境,执行时间为42449毫秒,CPU使用率为25%左右,4核中只使用了1和3的,而其他的都属于一般处理状态;

图1:

我们再来看一下使用并行计算后的相关数据:i5、4核测试环境,执行时间为19927毫秒,CPU利用率为100%,4核中全部到达顶峰;

图2:

这一个简单的测试例子,当然我只测试了两三组数据,基本上并行计算的速度要快于单线程的处理速度的2.1倍以上,当然还有其他因素在里面这里就不仔细分析了,起到抛砖引玉的作用;

3.1】并行For循环

在使用for循环的时候有相应的Parallel方式使用for循环,我们直接看一下示例代码,还是以上面的测试数据为例;

1 Parallel.For(0, orders.Count, index =>
2 {
3 //
4 });

第一个参数是索引的开始,第二个参数是循环总数,第三个是执行体,参数是索引值;使用起来其实很简单的;

3.2】并行ForEach循环

同样ForEach也是很简单的,还是使用上面的测试数据为例;

Parallel.ForEach(orders, order =>
{
order.IsSubmit = true;
int count = 0;
for (int i = 0; i < 2000; i++)
{
count++;
}
});

在Parallel类中有ForEach方法,第一个参数是迭代集合,第二个是每次迭代的item;

其实Parallel为我们封装了一个简单的调用入口,其实是依附于后台的Task框架的,因为我们常用的就是循环比较多,毕竟循环是任务的入口调用,所以我们使用并行循环的时候还是很方便的;

3.3】并行LINQ(PLINQ)

首先PLINQ是只针对Linq to Object的,所以不要误以为它也可以使用于Linq to Provider,当然自己可以适当的封装;现在LINQ的使用率已经很高了,我们在做对象相关的操作时基本上都在使用LINQ,很方便,特别是Select、Where非常的常用,所以.NET并行循环也在LINQ上进行了一个封装,让我们使用LINQ的时候很简单的使用并行特性;

LINQ核心原理的文章:http://www.cnblogs.com/wangiqngpei557/category/421145.html

根据LINQ的相关原理,知道LINQ是一堆扩展方法的链式调用,PLINQ就是扩展方法的集合,位于System.Linq.ParallelEnumerable静态类中,扩展于ParallelQuery<TSource>泛型类;

System.Linq.ParallelQuery<TSource>:

using System.Collections;
using System.Collections.Generic;

namespace System.Linq
{
// 摘要:
// 表示并行序列。
//
// 类型参数:
// TSource:
// 源序列中的元素的类型。
public class ParallelQuery<TSource> : ParallelQuery, IEnumerable<TSource>, IEnumerable
{
// 摘要:
// 返回循环访问序列的枚举数。
//
// 返回结果:
// 循环访问序列的枚举数。
public virtual IEnumerator<TSource> GetEnumerator();
}
}

System.Linq.ParallelEnumerable:

1 // 摘要:
2 // 提供一组用于查询实现 ParallelQuery{TSource} 的对象的方法。 这是 System.Linq.Enumerable 的并行等效项。
3 public static class ParallelEnumerable {}

我们在用的时候只需要将它原本的类型转换成ParallelQuery<TSource>类型就行了;

1 var items = from item in orders.AsParallel() where item.OName.Contains("1") select item;

Linq 的扩展性真的很方便,可以随意的封装任何跟查询相关的接口;

作者:王清培

出处:http://www.cnblogs.com/wangiqngpei557/

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

 
 

.NET并行计算基本介绍、并行循环使用模式的更多相关文章

  1. .NET并行编程实践(一:.NET并行计算基本介绍、并行循环使用模式)

    阅读目录: 1.开篇介绍 2.NET并行计算基本介绍 3.并行循环使用模式 3.1并行For循环 3.2并行ForEach循环 3.3并行LINQ(PLINQ) 1]开篇介绍 最近这几天在捣鼓并行计算 ...

  2. [No000088]并行循环vs普通循环

    using System; using System.Collections.Generic; using System.Threading; using System.Threading.Tasks ...

  3. C#并行编程(3):并行循环

    初识并行循环 并行循环主要用来处理数据并行的,如,同时对数组或列表中的多个数据执行相同的操作. 在C#编程中,我们使用并行类System.Threading.Tasks.Parallel提供的静态方法 ...

  4. .Net并行编程之二:并行循环

    本篇内容主要包括: 1.能够转化为并行循环的条件 2.并行For循环的用法:Parallel.For 3.并行ForEach的用法Parallel.ForEach 4.并行LINQ(PLINQ)的用法 ...

  5. ESP8266乐鑫版本的(支持云端升级 (Boot 模式)烧写方法,(V1.5.4官方介绍如下)(BOOT模式)

    硬件平台: nodeMCU devkit核心板,带ch340g,应该是仿造的,官方是cp2102驱动,安信可科技有连接https://wiki.ai-thinker.com/esp8266/board ...

  6. NSTimer定时器进阶——详细介绍,循环引用分析与解决

    引言 定时器:A timer waits until a certain time interval has elapsed and then fires, sending a specified m ...

  7. python使用rabbitMQ介绍二(工作队列模式)

    一模式介绍 第一章节的生产-消费者模式,是非常简单的模式,一发一收.在实际的应用中,消费者有的时候需要工作较长的时间,则需要增加消费者. 队列模型: 这时mq实现了一下几个功能: rabbitmq循环 ...

  8. hadoop(1)---hadoop的介绍和几种模式。

    一.什么是hadoop? Hadoop软件库是一个开源框架,允许使用简单的编程模型跨计算机集群分布式处理大型数据集.它旨在从单个服务器扩展到数千台计算机,每台计算机都提供本地计算和存储.库本身不是依靠 ...

  9. SQL连接操作符介绍(循环嵌套, 哈希匹配和合并连接)

    今天我将介绍在SQLServer 中的三种连接操作符类型,分别是:循环嵌套.哈希匹配和合并连接.主要对这三种连接的不同.复杂度用范例的形式一一介绍. 本文中使用了示例数据库AdventureWorks ...

随机推荐

  1. FloatyFish下载量

    老师之前没有统一好一个平台,为了公平起见,我们选择了知名度比较高的CSDN,上次课上给老师说的下载量已成为过去,我们目前的下载量是: 这里还有我们最真实的用户体验,来自CSDN的用户,而非我们的朋友: ...

  2. Android开发新手教程--Android应用程序结构

    一.新HelloWorld工程: 1.打开Eclipse.点击"File"->"New"->"Project"-Android ...

  3. StyleCop中有一些官方自己写好的检测规则下面就是英文的解释

    在StyleCop中有一些官方自己写好的检测规则下面就是英文的解释 文档规则 1.SA1600:ElementsMustBeDocumented元素必须添加注释 2.SA1601: PartialEl ...

  4. 房间计费系统改造E-R图纸设计

    简单的学习过程:     这几天忙得太混乱了,用了近一个星期才设计好.我在这段时间遇到的困难,就积极找师哥师姐指点迷津,如今多少总算是有些拿得出手的成果. 学习成果: Entity Relations ...

  5. Android开发之控制Toast的开启与关闭

    开发这个程序之前先解释一下,为什么Toast信息提示框在显示一定时间后会自己主动消失?由于在Android系统中有一个Toast队列,系统会依次从这个队列中取出一个Toast,并显示它.在显示了指定时 ...

  6. struts2的Action该方法不能去

    最近做的一个特征,使用struts2,input标签内容,并与相应的内容背景的实体类,当提交方法,无法进入action该方法和程序没有报错被,检验N通方法还没有找到,查找终于找到了,它是input标签 ...

  7. PDF.NET SOD Ver 5.1完全开源

    PDF.NET SOD Ver 5.1完全开源 前言: 自从我2014年下半年到现在的某电商公司工作后,工作太忙,一直没有写过一篇博客,甚至连14年股票市场的牛市都错过了,现在马上要过年了,而今天又是 ...

  8. Win8.1系统下配置搭建IIS8.5+PHP5.5.4运行环境

    原文 Win8.1系统下配置搭建IIS8.5+PHP5.5.4运行环境 很多人喜欢用linux搭建php网页语言运行环境,但由于linux高度自定义化,经常需要root运行命令,略显高端,相对应的微软 ...

  9. leetcode[73] Set Matrix Zeroes 将矩阵置零

    给定一个矩阵,把零值所在的行和列都置为零.例如: 1 2 3 1 3 1 1 1 操作之后变为 1 3 0 0 0 1 1 方法1: 赋值另存一个m*n的矩阵,在原矩阵为零的值相应置新的矩阵行和列为零 ...

  10. fscanf功能具体解释

    cfscanf fscanf fscanf : 格,fscanf格格 :int fscanf(FILE *stream, char *format,[argument...]); int fscanf ...