阅读目录:

  • 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. Cookbook of QUnit

    本篇文章是QUnit的简介,可以作为很好的入门教程.文章原址 介绍 自动化测试时软件开发过程中必不可少的一部分,而单元测试则是自动化测试的最为基本的一块,软件的每一个组件, 每一个功能单元都需要经过不 ...

  2. canvas 图片拖拽旋转之二——canvas状态保存(save和restore)

    引言 在上一篇日志“canvas 图片拖拽旋转之一”中,对坐标转换有了比较深入的了解,但是仅仅利用坐标转换实现的拖拽旋转,会改变canvas坐标系的状态,从而影响画布上其他元素的绘制.因此,这个时候需 ...

  3. 利用AE编写切图工具的一些探讨

    文章版权由作者李晓晖和博客园共有,若转载请于明显处标明出处:http://www.cnblogs.com/naaoveGIS/. 1.前言 这周利用晚上在家时间研究了下如何使用AE来开发切图工具.最初 ...

  4. ASP.NET Core中的ActionFilter与DI

    一.简介 前几篇文章都是讲ASP.NET Core MVC中的依赖注入(DI)与扩展点的,也许大家都发现在ASP.NET CORE中所有的组件都是通过依赖注入来扩展的,而且面向一组功能就会有一组接口或 ...

  5. 微信小程序:原生热布局终将改变世界

    关于本文的所有观点都是网上收集,与作者本人没有任何关系! 最近朋友圈已经被微信小程序刷屏了,这也难怪,腾讯的产品拥有广泛的影响力,谁便推出个东西,都会有很多人认为会改变世界,这不,张小龙刚一发布微信小 ...

  6. Cesium原理篇:2最长的一帧之网格划分

    上一篇我们从宏观上介绍了Cesium的渲染过程,本章延续上一章的内容,详细介绍一下Cesium网格划分的一些细节,包括如下几个方面: 流程 Tile四叉树的构建 LOD 流程 首先,通过上篇的类关系描 ...

  7. CSS padding margin border属性详解

    图解CSS padding.margin.border属性W3C组织建议把所有网页上的对像都放在一个盒(box)中,设计师可以通过创建定义来控制这个盒的属性,这些对像包括段落.列表.标题.图片以及层. ...

  8. javabean和jsp动作元素

    model1就是利用了jsp和javabean 的组合来处理问题.jsp页面如果有太多的逻辑代码的话,维护起来和扩展起来是相当的麻烦的.所以jsp的逻辑代码部分都打包到一种java类当中进行编写.这种 ...

  9. .Net语言 APP开发平台——Smobiler学习日志:实现在手机上调用摄像头进行扫描

    最前面的话:Smobiler是一个在VS环境中使用.Net语言来开发APP的开发平台,也许比Xamarin更方便 样式一 一.目标样式 我们要实现上图中的效果,需要如下的操作: 1.从工具栏上的&qu ...

  10. EF Core1.0 CodeFirst为Modell设置默认值!

    当我们使用CodeFirst时,有时候需要设置默认值! 如下 ; public string AdminName {get; set;} = "admin"; public boo ...