C#并发编程之初识并行编程
写在前面
之前微信公众号里有一位叫sara的朋友建议我写一下Parallel的相关内容,因为手中商城的重构工作量较大,一时之间无法抽出时间。近日,这套系统已有阶段性成果,所以准备写一下Parallel的相关内容,正好也延续之前的C#并发编程系列。
Parallel是并行编程的相关内容,而Parallel.For和Parallel.Foreach又是并行编程中相当重要的方法,所以不能孤立的去讨论Parallel,必须要放到并行编程的讨论中去。
并行化,一般是对所要完成的任务进行划分,并且以并发的方式处理属于自己的那份任务,并且最终可以做到整合,所以并行化总会产生并发性。
实际上并行是并发的子集,并发和并行都可以是多线程执行,就看其处理器是否是多核的,就看这些线程能不能同时被cpu多个核执行,如果可以就说明是并行,而并发是多个线程被cpu单核轮流切换着执行。总之,只有在多核处理器上并行才会有意义。
并行化总会有着很大的挑战,即每一个部分以不同顺序或者交错执行,都能保证最终结果的正确性,尤其涉及到各并行部分之间需要串行执行的部分,这个挑战是很大的。由于并行化程序设计要比普通的串行代码复杂很多,也难维护很多,所以不是所有的问题都可以使用并行的。比如绝对执行时间本来就很少,即使使用并发可以提高整体的执行时间,那么我们也应该使用传统方式。但是如果主要涉及到提升用户响应能力的功能,那么我们推荐使用并行编程,同时处理分割后依然可以独立进行而不影响整体任务的功能也可以使用并行编程。
并行的相关实战
说到并行,就需要先说下.NET FX4中引入的Task Parallel Library(任务并行库),简称TPL。TPL主要覆盖了三大使用场景,数据并行、任务并行和流水线,TPL以其高度的封装特性,隐藏了并行编程里复杂的处理,使得开发人员可以以较低的门槛进行并行编程。
数据并行
这种场景在于有大量数据需要处理,而且对每一份数据都要执行的同样的操作。

任务并行
有很多相对独立的不同操作,或者可以分割成多个子任务但彼此之间是独立的,可以通过任务并行来发挥并行化的优势
流水线
流水线是以上两种场景的结合,这个也是最复杂最难处理的场景,因为这里面涉及到多个并发的任务进行协调处理。
此场景,奈何小编理解的不是很好,所以不敢乱写,多方查找资料,找到了oschina上的一篇文章。
流水线技术,指的是允许一个机器周期内的计算机各处理步骤重叠进行。特别是,当执行一条指令时,可以读取下一条指令,也就意味着,在任何一个时刻可以有不止一条指令在“流水线”上,每条指令处在不同的执行阶段。这样,即便读取和执行每条指令的时间保持不变,而计算机的总的吞吐量提高了。
原文地址:https://my.oschina.net/u/3374461/blog/1930305
System.Threading.Tasks.Parallel类
虽然Parallel类在System.Threading.Tasks命名空间下,但是创建并行代码不一定要直接使用Task类的实例,事实上我们可以直接使用Parallel静态类所提供的方法。
Parallel.For:为固定数目的独立For循环迭代提供了负载均衡式的并行执行
1: Parallel.For(0, 5, i =>
2: {
3: Console.WriteLine("the number is", i);
4: });
Parallel.Foreach:为固定数目的独立ForEach循环迭代提供了负载均衡式的并行执行。这个方法支持自定义分区器(Partitioner),以使得我们截图完全掌控数据分发。
1: string[] letters = new string[] {"A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M"};
2: Parallel.ForEach(letters, i => Console.WriteLine("letter is " + i));
Parallel.Invoke:为给定的独立任务提供了负载均衡式的并行执行,接下来会重点讨论这个方法。
Parallel.Invoke
这个方法很实用,也很简单。
以下代码可以返回void的无参数方法:
1: Parallel.Invoke(Method1(), Method2(), Method3(), Method4());
通过Lambda表达式运行:
1: Parallel.Invoke(() => Method1(), () => Method2(), () => Method3(), () => Method4());
通过Lambda表达式和匿名类型来运行:
1: Parallel.Invoke(() =>
2: {
3: Method1();
4: // Do something
5: },
6: () =>
7: {
8: Method2();
9: // Do something
10: },
11: () =>
12: {
13: Method3();
14: // Do something
15: },
16: () =>
17: {
18: Method4();
19: // Do something
20: });
以上代码需要并行执行四个方法,但是如果空余逻辑内核不足四个或者根本就没有四个逻辑内核,这四个方法是不能并发执行的。因此在理想情况下,正好有至少四个空余逻辑内核时,我们就可以并行执行这四个方法了。
这四个方法,我们无法准确的预测其执行顺序,因为这一切是由底层的逻辑会根据运行时的现有可用资源创建出最合适的执行计划。当然TPL依然有机制保证方法的顺序执行,这个以后我们再讨论。
Parallel.Invoke最大的优势就是简单,但是并不能因为它简单,就不分场合的使用,事实上,我们需要在某些场景下权衡使用。
- 如果这四个方法的执行时间不一致,那么就需要根据最长的执行时间才能返回控制,这就可能造成一些逻辑内核处于闲置状态。所以我们需要预测一下大致的执行时间,如果时间过长,那么就要认真考虑是否真的需要使用这个方法。
- 其扩展性很差,因为它只能调用固定数目的逻辑内核,剩余内核就会一直处于闲置状态。
- 方法之间的交互极其困难,极易产生Bug,当然这是并行编程的常见问题,TPL也考虑到了这点,也有足够机制解决这个问题。
- 如果其中某个方法有了异常,捕捉异常会很困难,所以需要大家在相应的被调用方法里编写足够的日志。
- 小编在以前的使用中还遇到了内存溢出的异常,这些也会在以后的文章中说明其原因以及解决方法。
今天就写到这儿吧,已经十二点了,要休息一下,保护头发了,哈哈哈。
C#并发编程之初识并行编程的更多相关文章
- 五 浅谈CPU 并行编程和 GPU 并行编程的区别
前言 CPU 的并行编程技术,也是高性能计算中的热点,也是今后要努力学习的方向.那么它和 GPU 并行编程有何区别呢? 本文将做出详细的对比,分析各自的特点,为将来深入学习 CPU 并行编程技术打下铺 ...
- 第五篇:浅谈CPU 并行编程和 GPU 并行编程的区别
前言 CPU 的并行编程技术,也是高性能计算中的热点,也是今后要努力学习的方向.那么它和 GPU 并行编程有何区别呢? 本文将做出详细的对比,分析各自的特点,为将来深入学习 CPU 并行编程技术打下铺 ...
- C#并行编程-并发集合
菜鸟学习并行编程,参考<C#并行编程高级教程.PDF>,如有错误,欢迎指正. 目录 C#并行编程-相关概念 C#并行编程-Parallel C#并行编程-Task C#并行编程-并发集合 ...
- C#并行编程系列-文章导航
菜鸟初步学习,不对的地方请大神指教,参考<C#并行编程高级教程.pdf> 目录 C#并行编程-相关概念 C#并行编程-Parallel C#并行编程-Task C#并行编程-并发集合 C# ...
- C#并行编程-相关概念
菜鸟初步学习,不对的地方请大神指教,参考<C#并行编程高级教程.pdf> 目录 C#并行编程-相关概念 C#并行编程-Parallel C#并行编程-Task C#并行编程-并发集合 C# ...
- C#并行编程-Parallel
菜鸟学习并行编程,参考<C#并行编程高级教程.PDF>,如有错误,欢迎指正. 目录 C#并行编程-相关概念 C#并行编程-Parallel C#并行编程-Task C#并行编程-并发集合 ...
- C#并行编程-Task
菜鸟学习并行编程,参考<C#并行编程高级教程.PDF>,如有错误,欢迎指正. 目录 C#并行编程-相关概念 C#并行编程-Parallel C#并行编程-Task C#并行编程-并发集合 ...
- C#并行编程-线程同步原语
菜鸟学习并行编程,参考<C#并行编程高级教程.PDF>,如有错误,欢迎指正. 目录 C#并行编程-相关概念 C#并行编程-Parallel C#并行编程-Task C#并行编程-并发集合 ...
- C#并行编程-PLINQ:声明式数据并行
目录 C#并行编程-相关概念 C#并行编程-Parallel C#并行编程-Task C#并行编程-并发集合 C#并行编程-线程同步原语 C#并行编程-PLINQ:声明式数据并行 背景 通过LINQ可 ...
随机推荐
- softmax回归推导
向量\(y\)(为one-hot编码,只有一个值为1,其他的值为0)真实类别标签(维度为\(m\),表示有\(m\)类别): \[y=\begin{bmatrix}y_1\\ y_2\\ ...\\y ...
- synchronized 的真正含义
@synchronized 锁的永远是对象 ,只针对于对象,只能锁对象,常量等是不能加synchronized,一旦加编译也不会通过 @synchronized 锁对象中的非static 就是锁调用该 ...
- [一起读源码]走进C#并发队列ConcurrentQueue的内部世界 — .NET Core篇
在上一篇<走进C#并发队列ConcurrentQueue的内部世界>中解析了Framework下的ConcurrentQueue实现原理,经过抛砖引玉,得到了一众大佬的指点,找到了.NET ...
- 如何用python批量生成真实的手机号码
前言 文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理. 作者:Python测试社区 1目 标 场 景 平时在工作过程中,偶尔会需要大 ...
- 谁说 Vim 不好用?送你一个五彩斑斓的编辑器!
相信大家在使用各种各样强大的 IDE 写代码时都会注意到,代码中各种类型的关键字会用独特的颜色标记出来,然后形成一套语法高亮规则.这样不仅美观,而且方便代码的阅读. 而在上古神器 Vim 中,我们通常 ...
- react: typescript toastr
import toastr @types/toastr toastr.ts import * as toastr from "toastr" toastr.option.posit ...
- 文件上传漏洞(pikachu)
文件上传漏洞 文件上传功能在web应用系统很常见,比如很多网站注册的时候需要上传头像,附件等等.当用户点击上传按钮后,后台会对上传的文件进行判断,比如是否是指定的类型.后缀名.大小等等,然后将其按照设 ...
- awk和sed命令
awk awk是一个强大的编辑工具,可以在无交互的情况下实现相当复杂的文本操作 awk是行处理器: 相比较屏幕处理的优点,在处理庞大文件时不会出现内存溢出或是处理缓慢的问题,通常用来格式化文本信息 a ...
- 【Linux常见命令】paste命令
paste - merge lines of files paste 命令用于合并文件的列. paste 指令会把每个文件以列对列的方式,一列列地加以合并. 语法: paste [OPTION]... ...
- F查询,Q查询,事物,only与defer
F查询 之前的单表查询多表查询筛选条件都是一个固定的值,那么如何用字段来筛选呢? 比如 : 查询卖出数大于库存数的商品 这个时候我们就可以用到django里面的F查询了 查询示例表 ...