如何运用并行编程Parallel提升任务执行效率

本文来自小易,【DoTNET技术圈】公众号已获得转载授权。

《.NET并发变成实战》读后感:并行编程Parallel

手打目录:

一、前言

二、任务并行库(TPL)的介绍

三、Parallel.Invoke的使用

四、Parallel.For的使用

五、Parallel.ForEach+Partitioner的使用

六、指定最大并行度MaxDegreeOfParallelism

七、退出循环以及捕捉异常

八、参考的资料

一、前言

背景:在物联网场景下,由于数据吞吐量较大,常规的Task异步执行存在明显的性能瓶颈,后通过参考Riccardo Terrel(里卡尔多Dian·特雷尔)著,叶伟民老师翻译的《.NET并发编程实战》,使用了Parallel并行编程,以及分区器Partitioner,将两者结合使用提高了设备数据绑定及数据更新速度,也做到了对CPU的性能比较极致使用。

萌新记录,大佬多加斧正!

可跳过概念,直接抵达使用实例—>五、Parallel.ForEach+Partitioner的使用

并行编程的原理

在《.net并发编程实战》(以下称《实战》)中这样解释并行编程——同时执行多个任务。

从开发人员的角度看,当我们考虑这些问题是,“我的程序可以同时执行多项操作吗?”或“我的程序如何更快地解决一个问题”我们会想到并行。并行是指同时在不同的内核上执行多个任务,以提高应用程序的速度,这需要硬件支持(多核),且并行只能在多核设备中实现,是提高程序性能和吞吐量的手段。

并行与并发编程简单区分

1、 并发编程一次处理多个操作,不需要硬件支持(使用一个或多个内核)。

2、 并行编程在多个CPU或多个内核上同时执行多个操作。所有并行程序都是并发的,同时运行的,但并非所有并发都是并行的。原因是并行只能在多核设备上实现。

3、 多任务同时执行来自不同进程的多个线程。多任务并不一定意味着并行执行,只有在使用多个CPU 或多个内核时才能实现并行执行。

 

为什么需要使用并行编程

《实战》对不同程序CPU使用资源使用的程度做了一个对比: 

 

《实战》中认为,在一台多核计算机上运行一个没有考虑到并发的应用程序,就是在浪费计算机的生产力,因为应用程序在顺序处理过程中只能使用一部分可用的计算能力,在这种情况下任何CPU性能计数器会发现只有一个内核运行得很快,可能为100%,而其他内核未充分利用或空闲,在上图的8内核的计算机中,运行的非并行程序意味着资源的总体使用率可能不到15%。

使用并行编程的两种方式

1、 任务并行库(TPL),本文中只使用了这种方式

2、 并行LINQ(PLINQ)—》官方文档直达:https://docs.microsoft.com/zh-cn/dotnet/standard/parallel-programming/introduction-to-plinq

二、任务并行库(TPL)的并行介绍

.Net Framework4 引入了新的Task Parallel Library(任务并行库,TPL),它支持数据并行、任务并行和流水线。

当并行循环运行时,TPL会将数据源按照内置的分区算法(或者你可以自定义一个分区算法)将数据划分为多个不相交的子集,然后,从线程池中选择线程并行地处理这些数据子集,每个线程只负责处理一个数据子集。在后台,任务计划程序将根据系统资源和工作负荷来对任务进行分区。如有可能,计划程序会在工作负荷变得不平衡的情况下在多个线程和处理器之间重新分配工作。

在对任何代码(包括循环)进行并行化时,一个重要的目标是利用尽可能多的处理器,但不要过度并行化到使行处理的开销让任何性能优势消耗殆尽的程度。比如:对于嵌套循环,只会对外部循环进行并行化,原因是不会在内部循环中执行太多工作。少量工作和不良缓存影响的组合可能会导致嵌套并行循环的性能降低。

由于循环体是并行运行的,迭代范围的分区是根据可用的逻辑内核数、分区大小以及其他因素动态变化的,因此无法保证迭代的执行顺序。

    TPL引入了System.Threading.Tasks ,主类是Task,这个类表示一个异步的并发的操作,然而我们不一定要使用Task类的实例,可以使用Parallel静态类。它提供了Parallel.Invoke Parallel.ForParallel.Forecah 三个方法,以下分别介绍3个方法的简单实例,每个方法都有多个重载,可自行查看源代码

三、Parallel.Invoke的使用

        

static void Main(){try{Parallel.Invoke(BasicAction,// Param #0 - 静态方法() =>// Param #1 - lambda表达式{Console.WriteLine("干饭人干饭, Thread={0}", Thread.CurrentThread.ManagedThreadId);},delegate ()// Param #2 -  委托{Console.WriteLine("委托方法中, Thread={0}", Thread.CurrentThread.ManagedThreadId);});}// 在本例中不期望出现异常,但如果任务中仍然抛出异常,// 它将被包装在AggregateException中,并传播到主线程。catch (AggregateException e){Console.WriteLine("捕捉异常 \n{0}", e.InnerException.ToString());}}static void BasicAction(){Console.WriteLine("打工人打工, Thread={0}", Thread.CurrentThread.ManagedThreadId);}

 

 

注解:

l 此方法可用于执行可能并行执行的一组操作。

l 不保证执行操作的顺序,或是否并行执行操作。

l 此方法在每个提供的操作都已完成后才会返回,无论是由于正常终止还是异常终止而发生。

 

四、Parallel.For的使用

我们先用一个简单的插入,来比较并行的for循环与串行for循环的速度。

 

这里因为Parallel.For在对处理器分配任务时候也有性能消耗,速度提升并不明显。

 

接下来我们看一下Parallel.For的其中重载之一

 

          

var list = new List<int>() { 10, 20, 30, 40 };
var options = new ParallelOptions();
var total = 0;
var result = Parallel.For(0, list.Count, () =>{Console.WriteLine("------------  thead --------------");return 1;},(i, loop, j) =>{Console.WriteLine("------------  body --------------");Console.WriteLine("i=" + list[i] + " j=" + j);return list[i];},(b) =>{Console.WriteLine("------------  tfoot --------------");Interlocked.Add(ref total, b);Console.WriteLine("total=" + total);
});Console.WriteLine("iscompleted:" + result.IsCompleted);
Console.Read();

注解:

l 因为并行任务当中不保证执行顺序,且多任务可能会同时尝试更新total变量,所以这里使用了 Interlocked.Add执行,来保证它是作为原子操作来执行。

五、Parallel.ForEach+Partitioner的结合使用

Partitioner分区器:

首先我们来看看分区器源代码,看他是如何对数据源进行分区的:

 

Partitioner.Create 若只指定的数据源的起始于结束的索引位置,创建分区则主要是根据逻辑内核数(PlatformHelper.ProcessorCount)决定的。

 

 

 

大部分情况下,TPL在幕后使用的负载均衡机制都是非常高效的,比如我们不使用分区器,直接对数据源进行负载均衡的并行执行,案例请看—>六、指定最大并行度。

当然我们也可以自定义分区大小,以下我们进入到实际的开发环境中,当前实验电脑为6核12线程处理器

注解:

dataList —>实时数据的数据源

Index —>数据源总数,此处假设1W条数据

rangesize—>区块大小,由此可以计算  10000/12+1=834(+1是为了适应可能除不尽的情况)

Partitioner.Create(0,Index,rangesize) —>分区器将数据源0-1W条数据分成了12个数据块,每一块为834条,当然最后一块没有834条数据

 

 

打上断点可以看到range.Item2-range.Item1=834,已经分好区块了,然后就是并行处理业务代码了。

这里贴上示例,粘贴可用:

            

int index = 10000;
var rangesize = (int)(index / Environment.ProcessorCount) + 1;
var rangePartitioner = Partitioner.Create(1, index, rangesize);
System.Threading.Tasks.Parallel.ForEach(rangePartitioner, range =>{#region 业务代码#endregion
});

六、指定最大并行度MaxDegreeOfParallelism

参考博客文章:Parallel.ForEach 之 MaxDegreeOfParallelism

https://www.cnblogs.com/QinQouShui/p/12134232.html

 System.Threading.Tasks.Parallel.ForEach(list, new ParallelOptions() { MaxDegreeOfParallelism = 12 }, range =>{#region 业务代码#endregion});

此Parallel.ForEach并没有使用分区器,而是用TPL进行负载均衡的并行。

该重载的源代码为:

 

七、退出循环以及捕捉异常

和串行运行中的break不同,ParallelLoopState 提供了两个方法用于停止Parallel.For 和 Parallel.ForEach的执行。

 

public class ParallelLoopState
{// 获取循环的任何迭代是否已引发相应迭代未处理的异常。public bool IsExceptional { get; }// 获取循环的任何迭代是否已调用 ParallelLoopState.Stop()。public bool IsStopped { get; }// 获取在Parallel循环中调用 ParallelLoopState.Break() 的最低循环迭代。public long? LowestBreakIteration { get; }// 获取循环的当前迭代是否应基于此迭代或其他迭代发出的请求退出。public bool ShouldExitCurrentIteration { get; }//通知Parallel循环当前迭代”之后”的其他迭代不需要运行。public void Break();//通知Parallel循环当前迭代“之外”的所有其他迭代不需要运行。public void Stop();
}

 

l Break:用于通知Parallel循环当前迭代“之后”的其他迭代不需要运行。例如,对于从 0 到 1000 并行迭代的 for 循环,如果在第 100 次迭代调用 Break(),则低于 100 的所有迭代仍会运行(即使还未开始处理),并在退出循环之前处理完。从 101 到 1000 中还未开启的迭代则会被放弃。对于已经在执行的长时间运行迭代,Break()将为已运行还未结束的迭代对应ParallelLoopResult结构的LowestBreakIteration属性设置为调用Bread()迭代项的索引。

l Stop:Stop() 用于通知Parallel循环当前迭代“之外”的所有其他迭代不需要运行,无论它们是位于当前迭代的上方还是下方。对于已经在执行的长时间运行迭代,可以检查 IsStopped属性,在观测到是 true 时提前退出。Stop 通常在基于搜索的算法中使用,在找到一个结果之后就不需要执行其他任何迭代。(比如在看视频或漫画时自动匹配响应最快的服务器)

var loopresult = System.Threading.Tasks.Parallel.ForEach(rangePartitioner, range =>
{#region 业务代码loopState.Stop();#endregion
});

 

 

 

 当并行迭代中调用的委托抛出异常,这个异常没有在委托中被捕获到时,就会变成一组异常,新的System.AggregateException负责处理这一组异常。

try
{System.Threading.Tasks.Parallel.ForEach(rangePartitioner, range =>{#region 业务代码#endregion});
}
Catch(AggregateException ex)
{foreach (var innerEx in  ex.InnerExceptions){Console.WriteLine(innerEx.ToString());}
}

八、参考的资料

l 《.net并发编程实战》

l 官方文档《.NET 中的并行编程》https://docs.microsoft.com/zh-cn/dotnet/standard/parallel-programming/

l 博客园《.Net并行编程高级教程--Parallel》https://www.cnblogs.com/stoneniqiu/p/4857021.html

l 博客园《8天玩转并发》

https://www.cnblogs.com/huangxincheng/category/368987.html

l 《异步编程:.NET4.X 数据并行》

https://www.cnblogs.com/heyuquan/archive/2013/03/13/parallel-for-foreach-invoke.html

l 博客园《Parallel.ForEach 之 MaxDegreeOfParallelism》

https://www.cnblogs.com/QinQouShui/p/12134232.html

 end

 

输入优惠码同样也能享受到当当送的优惠。

RCKZEV(长按复制)10元优惠码(满99元可用)

7R99RD(长按复制)30元优惠码(满199元可用)

使用渠道:当当小程序或当当APP

有效期:323日至3月25日

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/303768.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

通过 GitHub Actions 自动创建 Github Release

通过 GitHub Actions 自动创建 Github ReleaseIntro在 GitHub 上维护了几个小的开源项目&#xff0c;每次在发布新版本的时候会创建一个 release&#xff0c;这样可以比较方便的找到对应的版本的代码&#xff0c;不需要再人肉的从 git log 中找到指定的 commit&#xff0c;而且…

利用win7的applocker功能来有组织的阻止相关软件运行

我有4年没用360相关的软件了&#xff0c;没有360的弹窗用电脑就是舒服。但是我的电脑有时候会有别人来用&#xff0c;我的同学或者我的父母。但是他们经常会自作主张地在我的电脑上装上360卫士&#xff0c;还有360浏览器。每次都是装了我再删&#xff0c;反反复复也不是办法。后…

人工智能会让工作环境变得更公平,还是更压抑?

人工智改变的不仅仅是工作内容……人工智能&#xff08;AI&#xff09;正在踏足商业领域。正如我们本周的特别报道所诠释到的那样&#xff0c;所有类型的公司都在利用人工智能来预测需求&#xff0c;雇佣员工和对付客户。2017年&#xff0c;企业在与人工智能相关的并购交易中支…

离开时请告诉自己生意就是生意

离开时请告诉自己生意就是生意 离职或者被离职&#xff0c;是职场中很常见的事情&#xff0c;每天这个星球上不知道要发生多少次&#xff0c;不管你经历过与否、体会到其中的滋味与否&#xff0c;他都会一直存在着&#xff01;当这一切发生时&#xff0c;不管你是获利者还是受害…

如何假装成一名好程序员?

最近我对一位资深程序员就工作生活问题进行了深度采访&#xff0c;采访内容如下&#xff1a;Q&#xff1a;请问你工作多久了&#xff1f;A&#xff1a;5年了Q&#xff1a;你觉得&#xff0c;程序员这份工作对你有什么影响吗&#xff1f;A&#xff1a;有Q&#xff1a;那你的生活…

c语言 gbk字模点阵数组,GBK点阵显示字库的制作和使用

GBK编码共收录汉字21003个、符号883个&#xff0c;并提供1894个造字码位&#xff0c;简、繁体字融于一库。以两个字节表示一个汉字&#xff0c;编码范围是0x8140~0xfefe&#xff0c;兼容GB2318&#xff0c;并覆盖了unicode中的所有汉字。Win7记事本默认以GBK保存汉字。开发环境…

云服务器下行_腾讯云轻量应用服务器简单测评

这台机器的配置是1核心1G内存3M带宽,一直在吃灰&#xff0c;到现在才想起来应该测评一下腾讯云活动推荐​cloud.tencent.com测评机器概况从图中可以看到这台机器CPU采用 AMD EPYC 7K62 48-Core Processor 主频2.60GhzI/O大致129.3MB/S 用来建站是没问题的。3Mbps上行带宽跑满,下…

这是我见过的最全的训练数据集,没有之一!

从大学毕业起&#xff0c;小编就开始收集各类数据集&#xff0c;经过近几年的积累和沉淀&#xff0c;小编收集整理了32套数据集&#xff0c;内容涵盖“自动驾驶”、“人脸识别”、“世界杯”、“股票数据”、“基因组数据”、“全球各大社交媒体数据”等。现在&#xff0c;小编…

运维小姐姐说这篇Consul集群和ACL配置超给力(保姆级)

前言上一篇简单介绍了Consul&#xff0c;并使用开发模式&#xff08;dev&#xff09;进行流程演示&#xff0c;但在实际开发中需要考虑Consul的高可用和操作安全性&#xff0c;所以接着来聊聊集群和ACL的相关配置&#xff0c;涉及到的命令会在环境搭建过程中详细介绍。正文关于…

c语言判断x的个位数是否为5,用C语言编程从键盘输入一个正整数,判断其个位数是否为5,若是5则输出“yes”,否则输出“no”...

#include int main(){int five;printf("输入一个整数:");scanf("%d",&five);while(five>10){five five%10;}if(five 5)printf("yes");elseprintf("no");return 0;}扩展资料&#xff1a;“模”是“Mod”的音译&#xff0c;模运…

从基础概念到数学公式,这是一份520页的机器学习笔记(图文并茂)

导读&#xff1a;近日&#xff0c;来自SAP&#xff08;全球第一大商业软件公司&#xff09;的梁劲&#xff08;Jim Liang&#xff09;公开了自己所写的一份 520 页的学习教程&#xff08;英文版&#xff09;&#xff0c;详细、明了地介绍了机器学习中的相关概念、数学知识和各种…

Excel模板导出之动态导出

说明目前Magicodes.IE已支持Excel模板导出时使用JObject、Dictionary和ExpandoObject来进行动态导出&#xff0c;具体使用请看本篇教程。本功能的想法、部分实现初步源于arik的贡献&#xff0c;这里再次感谢arik&#xff01;在开始本篇教程之前&#xff0c;我们重温一下模板导出…

简述原型模型的特点_3D打印硅胶复模手板的步骤和特点有哪些

硅胶手板是一种主要用于手板模制作的硅胶制品&#xff0c;手板硅胶主要要求&#xff1a;不缩水、不变形&#xff0c;硬度合适不太复杂的产品使用。硅胶手板经常用硅胶模具来制造为产品快速成型复制提供便利性&#xff0c;产品收缩率可达到千分之二&#xff0c;主要用于手板模型…

快速成长为数据挖掘高手的秘诀

随着大数据时代的到来&#xff0c;数据挖掘的重要性越发显著。所谓数据挖掘&#xff0c;一般是指从大型数据库中将隐藏的预测信息抽取出来的过程&#xff0c;而更为精确的解释就是“从数据中挖掘知识”。目前而言&#xff0c;数据挖掘大致分为四个层次&#xff1a;纯粹数据加工…

ASP.NET Core 基于角色的 JWT 令牌

原文&#xff1a;https://bit.ly/3vYljq3作者&#xff1a;Rick Strahl翻译&#xff1a;精致码农-王亮声明&#xff1a;我翻译技术文章不是逐句翻译的&#xff0c;而是根据我自己的理解来表述的。其中可能会去除一些本人实在不知道如何组织但又不影响理解的句子。ASP.NET Core 中…

圆形比例分布图怎么做_解读宝山区2035总体规划:建设用地的比例在上海非中心城区中最高...

《上海市宝山区总体规划暨土地利用总体规划(2017-2035)》已经发布&#xff0c;在宝山区2035总体规划中&#xff0c;一个重要的核心指标成为了亮点&#xff0c;这就是宝山区的建设用地面积为244.3平方公里。宝山区的陆地总面积是301.6平方公里&#xff0c;由此宝山区建设用地面积…

Lanchester战争模型:用可分离变量的微分方程占卜战事

看过国产的战争题材电视剧《亮剑》的各位老铁一定熟悉李云龙集结重兵攻打县城的故事。在故事中&#xff0c;李云龙利用人数上的优势对平安县城进行了围点打援&#xff0c;最后用二营长的意大利炮消灭了城楼上的鬼子官。但是众所周知&#xff0c;抗日时期中国军队的单兵作战能力…

微软软件安装平台

http://www.microsoft.com/web/downloads/platform.aspx 转载于:https://www.cnblogs.com/kkun/archive/2011/03/09/1978039.html

如何在 C# 中使用 yield

yield关键词是在 C# 2.0 中被引入的&#xff0c;我们都知道实现了 IEnumerable 接口的类都可以用于被 foreach 迭代&#xff0c;这是因为 IEnumerable 接口中提供了一个可迭代的 GetEnumerator() 方法&#xff0c;代码定义如下&#xff1a;public interface IEnumerable{IEnume…

通过听力写代码?盲人程序员就是这样做的

一Michael Forzano&#xff0c;Amazon2018 年 3 月&#xff0c;Amazon 官网「工作在 Amazon」栏目有一篇文章&#xff0c;介绍了他们的一位盲人程序员 Michael Forzano。&#xff08;视频来自&#xff1a;阑夕&#xff09;Amazon 软件工程师 Michael Forzano 出生就因先天疾病而…