阅读目录:

  • 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 = ; i < ; 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 = ;
for (int i = ; i < ; 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 = ;
for (int i = ; i < ; 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循环,我们直接看一下示例代码,还是以上面的测试数据为例;

 Parallel.For(, orders.Count, index =>
{
//
});

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

3.2】并行ForEach循环

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

 Parallel.ForEach(orders, order =>
{
order.IsSubmit = true;
int count = ;
for (int i = ; i < ; 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:

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

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

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

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

作者:王清培

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

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

.NET并行编程实践(一:.NET并行计算基本介绍、并行循环使用模式)的更多相关文章

  1. 【读书笔记】.Net并行编程高级教程(二)-- 任务并行

    前面一篇提到例子都是数据并行,但这并不是并行化的唯一形式,在.Net4之前,必须要创建多个线程或者线程池来利用多核技术.现在只需要使用新的Task实例就可以通过更简单的代码解决命令式任务并行问题. 1 ...

  2. .Net并行编程高级教程(二)-- 任务并行

    前面一篇提到例子都是数据并行,但这并不是并行化的唯一形式,在.Net4之前,必须要创建多个线程或者线程池来利用多核技术.现在只需要使用新的Task实例就可以通过更简单的代码解决命令式任务并行问题. 1 ...

  3. .Net并行编程(一)-TPL之数据并行

    前言 许多个人计算机和工作站都有多个CPU核心,可以同时执行多个线程.利用硬件的特性,使用并行化代码以在多个处理器之间分配工作. 应用场景 文件批量上传 并行上传单个文件.也可以把一个文件拆成几段分开 ...

  4. OpenMP共享内存并行编程详解

    实验平台:win7, VS2010 1. 介绍 平行计算机可以简单分为共享内存和分布式内存,共享内存就是多个核心共享一个内存,目前的PC就是这类(不管是只有一个多核CPU还是可以插多个CPU,它们都有 ...

  5. C#并行编程-相关概念

    菜鸟初步学习,不对的地方请大神指教,参考<C#并行编程高级教程.pdf> 目录 C#并行编程-相关概念 C#并行编程-Parallel C#并行编程-Task C#并行编程-并发集合 C# ...

  6. OpenMP并行编程

    什么是OpenMP?“OpenMP (Open Multi-Processing) is an application programming interface (API) that support ...

  7. Linux多核并行编程关键技术

    多核并行编程的背景 在摩尔定律失效之前,提升处理器性能通过主频提升.硬件超线程等技术就能满足应用需要.随着主频提升慢慢接近撞上光速这道墙,摩尔定律开始逐渐失效,多核集成为处理器性能提升的主流手段.现在 ...

  8. C#并行编程(1):理解并行

    什么是并行 并行是指两个或者多个事件在同一时刻发生. 在程序运行中,并行指多个CPU核心同时执行不同的任务:对于单核心CPU,严格来说是没有程序并行的.并行是为了提高任务执行效率,更快的获取结果. 与 ...

  9. C#并行编程系列-文章导航

    菜鸟初步学习,不对的地方请大神指教,参考<C#并行编程高级教程.pdf> 目录 C#并行编程-相关概念 C#并行编程-Parallel C#并行编程-Task C#并行编程-并发集合 C# ...

随机推荐

  1. 韩国"被申遗" (转自果壳)

    "被申遗"不是指"没申遗",而是全都经过了中国人重新包装. 近日,有报道称韩国计划将火炕申报世界遗产,联系近年来韩国多起"申遗事件",国内网 ...

  2. 相克军_Oracle体系_随堂笔记013-字符集

    linux环境下: [root@single ~]# locale LANG=en_US.UTF-8 LC_CTYPE="en_US.UTF-8" …… windows环境下: C ...

  3. 利用js2image把代码压缩成圣诞树

    马上圣诞节了,作为一名程序猿,如何体现自己独特的过节风格,如何在朋友圈发一张专属自己的祝福照片我觉得很有必要,你们说是不是. 谈到圣诞节,话说程序猿和圣诞之间的关系还有这么一个笑话: Q:程序员为什么 ...

  4. 30行代码让你理解angular依赖注入:angular 依赖注入原理

    依赖注入(Dependency Injection,简称DI)是像C#,java等典型的面向对象语言框架设计原则控制反转的一种典型的一种实现方式,angular把它引入到js中,介绍angular依赖 ...

  5. ASP.NET多种不同页面间数据传递的方法

    1. Get(即使用QueryString显式传递)     方式:在url后面跟参数.     特点:简单.方便.     缺点:字符串长度最长为255个字符:数据泄漏在url中.     适用数据 ...

  6. 设计模式(五)建造者模式(Builder Pattern)

    一.引言 在软件系统中,有时需要创建一个复杂对象,并且这个复杂对象由其各部分子对象通过一定的步骤组合而成.例如一个采购系统中,如果需要采购员去采购一批电脑时,在这个实际需求中,电脑就是一个复杂的对象, ...

  7. 【C#进阶系列】28 基元线程同步构造

    多个线程同时访问共享数据时,线程同步能防止数据损坏.之所以要强调同时,是因为线程同步问题实际上就是计时问题. 不需要线程同步是最理想的情况,因为线程同步一般很繁琐,涉及到线程同步锁的获取和释放,容易遗 ...

  8. 转载:《TypeScript 中文入门教程》 5、命名空间和模块

    版权 文章转载自:https://github.com/zhongsp 建议您直接跳转到上面的网址查看最新版本. 关于术语的一点说明: 请务必注意一点,TypeScript 1.5里术语名已经发生了变 ...

  9. FilterDispatcher已被标注为过时解决办法 &gt;&gt;&gt; FilterDispatcher &lt;&lt;&lt; is deprecated!

    一些struts2的教程都是比较早的,当我们基于较新版本的struts2来实现代码的时候,往往会出现一些问题.比如这个警告:FilterDispatcher isdeprecated! 在web.xm ...

  10. Javaweb——过滤器映射

    什么是过滤器? 过滤器:从字面上看,可以理解为将具有杂质的水过滤,留下干净的水.那么从IT的角度上理解.过滤器:是处在源数据(数据库之类的)和目标数据(显示页面)的中间组件.对于Web应用来说,过滤器 ...