C#并行编程(1):理解并行
什么是并行
并行是指两个或者多个事件在同一时刻发生。
在程序运行中,并行指多个CPU核心
同时执行不同的任务;对于单核心CPU,严格来说是没有程序并行的。并行是为了提高任务执行效率,更快的获取结果。
与并发的区别:
并发是指两个或者多个事件在同一时段发生。
相对于并行,并发强调的是同一时段,是宏观上的同时发生。实际上,同一时刻只有一个任务在被执行,多个任务是分时地交替执行的。并发是为了更合理地分配资源。
如何实现并行
并行编程中我们只关注应用层面的并行,CPU的指令并行技术(指令流水等)不在我们的考虑范围。
从并行的意义来看,并行编程的目的无非是让多个CPU核心同时执行不同业务逻辑,获取优良的性能。但是,要怎样实现并行呢?实现并行,我们要借助进程
和线程
。
为了更好地管理计算机中运行的程序,计算机操作系统引入进程
:
狭义定义:进程是正在运行的程序的实例(an instance of a computer program that is being executed)。
广义定义:进程是一个具有一定独立功能的程序关于某个数据集合的一次运行活动。
——百度百科
由于进程拥有计算机资源,在创建、切换和撤销的过程中开销较大,这就限制了进程的并发程度;多核CPU的日渐普及的环境下,为提高并行粒度和并行计算的效率,引入了一种轻型的进程——线程
:
线程(英语:thread)是操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运作单位。
——百度百科
线程包含于进程,同一进程的线程共享该进程的资源。线程出现后,线程取代进程作为操作系统调度和分派的基本单位,极大地减少了进程切换带来的性能损失,使得更细粒度和更高性能的并行得以实现。
进程的调度
一台计算机会运行很多程序,这些程序进程的数量多会大于CPU的核心数量。每个CPU核心同一时间只能执行一个进程,那操作系统是如何管理这些进程的呢?
当启动一个程序的实例时,操作系统将创建一个进程用来调度该程序实例。一个进程主要包含以下的信息:
进程控制块PCB,用于操作系统控制该程序实例
进程标识信息,如PID、名称等
现场信息,存放进程运行时处理器现场信息
控制信息,存放操作系统用于管理和调度进程的信息
专有的虚拟地址空间
句柄列表
程序实例的代码和数据,被映射到进程私有虚拟地址空间
程序状态字信息
进程的状态模型,如下图:
操作系统按照进程状态进行程序调度。
启动程序时,操作系统创建进程,此时进程为
新建
态运行资源充足时,操作系统提交进程到
就绪
状态,等待CPU选择或者抢占CPU执行运行资源不足,如主存不够,操作系统会挂起进程,进程状态改为
就绪挂起
,等待操作系统的恢复
就绪状态的进程
CPU空闲时,会选择执行就绪状态的进程,被选中的进程进入
运行状态
进程优先级高时,将抢占当前正在执行进程的CPU资源,自身进入运行状态
操作系统会根据当前的可用资源,把就绪状态的进程挂起
就绪挂起的进程
当前没有就绪的进程,或者就绪挂起的某个进程具有较高的优先级,操作系统会将就绪挂起的进程恢复到就绪状态
运行状态的进程
进程自然结束、被强制终结或者出现无法解决的异常,将进入
终止
状态,终止的线程不再参与进程调度进程到达运行的时间片或者出现优先级高的进程抢占了CPU,进程会回到就绪状态等待调度
进程等待资源、I/O或者信号时,会进入
阻塞
状态优先级较高的进程抢占CPU,而此时系统资源不足,则正在运行的线程会被转入就绪挂起状态
阻塞状态的进程
进程阻塞的条件被满足,如等待的资源到位、I/O完成或收到信号,会进入就绪状态
进程在等待资源、I/O或者信号时,若系统检测到运行资源不足,会将阻塞的进程挂起进入
阻塞挂起
状态
阻塞挂起的进程
当被挂起的进程具有较高优先级,同时由于其他进程的退出使资源充裕,进程会被转为阻塞状态
挂起的阻塞进程得到资源、I/O完成或者收到信号后,被转入就绪挂起状态
上述便是进程的调度过程,其中挂起的进程不占有任何资源。进程的调度很大程度是依赖于运行资源的;进程的优先级也是影响进程调度的重要因素;此外进程的调度还会涉及进程间的通信和同步问题,这里不做展开。
实际上,相对于进程,在并行编程中我们更关心线程,因为线程才是系统调度的基本单位。
线程的调度
在Windows系统中,每个进程至少有一个线程,每个线程都包含下面的内容:
线程内核对象,包含线程上下文(包含CPU寄存器信息的内存块)
线程环境块,包含线程的异常处理链首、本地存储数据等
用户模式栈,存储传给方法的局部变量和实参
内核模式栈,线程调用操作系统内核函数时,所传实参从用户模式栈复制到内核模式栈
DLL线程连接和分离,线程创建和销毁时,所依赖的DLL需要收到通知才能执行相关资源的初始化和清理
从线程所含内容,我们可以知道线程的创建和销毁是有着时间和空间开销的,虽然这些开销相较于进程来说小了很多,但仍是影响程序效率的重要因素。特别是在并行处理的时候,线程的频繁创建和销毁将对并行性能产生极为严重的影响。
系统同一时间只给一个CPU核心分配一个线程,CPU执行该线程达一个时间片后,系统会给该CPU核心分配另一个线程。系统分配线程至CPU核心的过程就是线程的上下文切换过程,此间,系统将执行3个动作:
把CPU寄存器的值保存到正在运行的线程上下文中
从现有线程集合中选取一个线程准备分配
把选中线程上下文中保存的CPU寄存器值加载到CPU寄存器中
线程上下文切换会对程序性能带来很严重的影响,特别是切换到一个新进程的新线程时,很可能需要从RAM中加载代码和数据,大家知道RAM相对于CPU高速缓存太慢了。
线程的创建、切换及销毁都是有着不可忽视的开销,在追求高性能的程序中,我们应尽量少地线程,最优性能的线程数是机器CPU的核心数。当然,性能只是程序的一个方面,响应性和可靠性也是要关注的重点。
小结
并行在进程层面依赖于系统可用系统资源和CPU核心数,单核CPU的程序并行,实质上是并发;在线程层面则主要依赖于CPU核心数以及我们安排线程的方式。
后续将以.NET为例总结并发编程。
注:本文关于进程和线程的相关内容以Windows操作系统为参考。
原文地址:https://www.cnblogs.com/chenbaoshun/p/10535374.html
.NET社区新闻,深度好文,欢迎访问公众号文章汇总 http://www.csharpkit.com
C#并行编程(1):理解并行相关推荐
- c语言mpi并行程序,高性能计算之并行编程技术MPI并行程序设计(完整版).pdf
高性能计算之并行编程技术MPI并行程序设计(完整版) 高性能计算之并行编程技术 -- MPI并行程序设计 都志辉 编著 李三立 审阅 陈渝 刘鹏 校对 I 内容提要 本书介绍目前最常见的并行程序- M ...
- 如何进行并行编程:从并行矩阵运算开始
矩阵计算 矩阵计算问题有很多种类型,例如: 求解线性代数方程组 Ax = b 线性最小二乘问题 given b in R^m, for x in R^n,minimize ||Ax - b||^2 矩 ...
- dnet 并行编程学习总结
.Net并行编程高级教程--Parallel http://www.cnblogs.com/stoneniqiu/p/4857021.html 一直觉得自己对并发了解不够深入,特别是看了<代码整 ...
- C#并发编程之初识并行编程
写在前面 之前微信公众号里有一位叫sara的朋友建议我写一下Parallel的相关内容,因为手中商城的重构工作量较大,一时之间无法抽出时间.近日,这套系统已有阶段性成果,所以准备写一下Parallel ...
- C#并行编程-并发集合
菜鸟学习并行编程,参考<C#并行编程高级教程.PDF>,如有错误,欢迎指正. 目录 C#并行编程-相关概念 C#并行编程-Parallel C#并行编程-Task C#并行编程-并发集合 ...
- .Net并行编程系列文章导航
.Net4.0并行编程系列文章如下: 多核时代 .NET Framework 4 中的并行编程9---线程安全集合类 多核时代 .NET Framework 4 中的并行编程8---任务的同步 多核时 ...
- Python 并行编程教程 | Lynda教程 中文字幕
Python 并行编程教程 | Lynda教程 中文字幕 Python Parallel Programming Solutions 课程ID: 604237 时长: 4.0小时 所属类别:Pytho ...
- 并行:并行编程的基础概述
并行编程的目的 并行编程主要有三个目的:性能(performance),通用性(versatility),生产率(productivity).简称PVP 注意区分并行和并发的概念: 并行:一个任务可以 ...
- MPI并行程序开发设计----------------------------------并行编程模型和算法等介绍
---------------------------------------------------------------------------------------------------- ...
- Delphi xe7并行编程快速入门
现在多数设备.计算机都有多个CPU单元,即使是手机也是多核的.但要在开发中使用多核的优势,却需要一些技巧,花费时间编写额外的代码.好了,现在可以使用Delphi做并行编程了. 在Delphi.C++ ...
最新文章
- 博士生起诉学校,因核心期刊发文数不够申请学位被拒,一审判决胜诉!
- 如何创建高效的业务连续性计划
- 【励志好文】老爸推荐的好文,受益良多!
- Java注解研究之@Required
- 消灭WinRAR广告
- Linux应急响应篇
- kronecker引理证明_连续型Kronecker引理
- 「三代组装」使用Pilon对基因组进行polish
- 关于一维数组(小朋友都能明白的一维数组超详细介绍)
- WeChatTweak-微信小助手 v1.2.2 详细安装教程
- Python Text Processing with NLTK 2.0 Cookbook代码笔记
- 洛谷P1217 [USACO1.5]回文质数 Prime Palindromes
- 【新股分析】知名分销商双财庄将登陆港交所:复合年增长率高达16.02%
- 细数抖音电商的7问题
- 非激活窗口(Inactive Window)
- java环境一键_Java环境变量一键配置
- Kali渗透测试之端口扫描1——UDP、TCP、僵尸扫描、隐蔽扫描
- Linux操作系统应用实例_Discuz安装
- Unity半透明特效原理讲解(为什么半透明设置渲染顺序和深度写入这么重要)
- 解决ramdisk卸载后重新安装设备管理器中无法找到ramdisk设备问题