提交 9f779ba6 编写于 作者: chyyuu1972's avatar chyyuu1972

finish init version of ch5:4 add multiprocessor sched

上级 6344889a
......@@ -472,21 +472,81 @@ EDF调度算法按照进程的截止时间的早晚来分配优先级,截止
多处理器计算机系统的调度
----------------------------------
在2000年前,多处理器计算机的典型代表是少见的高端服务器和超级计算机,但到了2000年后,单靠提高处理器的频率越来越困难,而芯片的集成度还在进一步提升,所以在一个芯片上集成多个处理器核成为一种自然的选择。到目前位置,在个人计算机、以手机为代表的移动终端上,多核处理器(Multi Core)已成为一种普遍的现象,多个处理器核能够并行执行,且可以共享Cache和内存。
之前提到的调度策略/算法都是面向单处理器的,如果把这些策略和算法扩展到多处理器环境下,是否需要解决新问题?
.. note::
并行处理需要了解更多的硬件并行架构问题和软件的同步互斥等技术,而深入的硬件并行架构目前不在本书的范畴之内,同步互斥等技术在后续章节才介绍。按道理需要先学习这些内容才能真正和深入理解本小节的内容,但本小节的内容在逻辑上都属于进程调度的范畴,所以就放在这里了。建议可以先大致学习本小节内容,在掌握了进程间同学、同步互斥等技术后,再回头重新学习一些本小节内容。
约束条件
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
为了理解多处理器调度需要解决的新问题,我们需要理解单处理器计算机与多处理器计算机的基本区别。对于多处理器计算机而言,每个处理器核心会有共享的Cache,也会有它们私有的Cache,而各自的私有Cache中的数据有硬件来保证数据的Cache一致性(也称缓存一致性)。
.. chyyuu 画一个图,说明多核处理器结构
简单地说,位于不同私有Cache中的有效数据(是某一内存单元的值)要保证是相同的,这样处理器才能取得正确的数据,保证计算的正确性,这就是Cache一致性的基本含义。保证一致性的控制逻辑是由硬件来完成的,对操作系统和应用程序而言,是透明的。
在共享Cache和内存层面,由于多个处理器可以并行访问位于共享Cache和内存中的共享数据,所以需要有后面章节讲解的同步互斥机制来保证程序执行的正确性。这里,我们仅仅介绍一下简单的思路。
以给创建的新子进程设置进程号为例。在单处理器情况下,操作系统用一个整型全局变量保存当前可用进程号,初始值为 0 。给新进程设置新进程号的过程很简单:
1. 新进程号= 当前可用进程号;
2. 当前可用进程号 = 当前可用进程号 + 1;
在多处理器情况下,假设两个位于不同处理器上的进程都发起了创建子进程的系统调用请求,操作系统可以并行地执行创建两个子进程,而且需要给子进程设置一个新的进程号。如果没有一些同步互斥的手段,那么可能出现如下的情况:
t0: ID-PA = CurID ID-PB= CurID
t1: CurID = CurID+1 CurID = CurID +1
这样两个新进程的进程号就是一样的了,这就会在后续的执行中出现各种问题。为了正确处理共享变量,就需要用类似互斥锁(Mutex)的方法,让在不同处理器上执行的控制流互斥地访问共享变量,这样就能解决正确性问题。
所以,对于多处理器下运行的进程而言,新增加了如下的假设条件:
1. 运行在不同处理器上的多个进程可用并行执行,但对于共享资源/变量的处理,需要有同步互斥等机制的正确性保证。
性能指标
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
这里的性能指标与之前描述的基于单处理器的通用计算机系统一样,主要是周转时间、响应时间和公平性。
单队列调度
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
对于多处理器系统而言,两个进程数量多于处理器个数,我们希望每个处理器都执行进程。这一点是之前单处理器调度不会碰到的情况。单处理器的调度只需不断地解答:“接下来应该运行哪个进程?”,而在多处理机中,调度还需解答一个问题:“要运行的进程在哪一个CPU上运行?”。这就增加了调度的复杂性。
如果我们直接使用单处理器调度的数据结构,其中的重点就是放置就绪进程的就绪队列或其他与调度相关的数据结构。那么这些数据结构就是需要互斥访问的共享数据。 为简化分析过程,我们以轮转调度采用的单就绪队列为例,面向多处理器的单队列调度的策略逻辑没有改变,只是在读写/修改就绪队列等共享数据时,需要用同步互斥的一些操作保护起来,确保对这些共享数据访问的正确性。
采用单队列调度的一个好处是,它支持自动负载平衡,因为决不会出现一个CPU空闲而其他CPU过载的情况。
**处理器亲和性**
另外,还需考虑的一个性能问题是调度中的处理器亲和性(也称缓存亲和性、调度亲和性)问题。其基本思想是,尽量使一个进程在它前一次运行过的同一个CPU上运行。其原因是,现代的处理器都有私有Cache,基于局部性的考虑,如果操作系统在下次调度时要给该进程选择处理器,会优先选择该进程上次执行所在的处理器,从而使得Cache中缓存的数据可重用,提高了进程执行的局部性。
多队列调度
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
如果处理器的个数较多,频繁对共享数据执行同步互斥操作的开销会很大。为此,能想到的一个方法是,还是保持单处理器调度策略的基本逻辑,但把就绪队列或和他与调度相关的数据结构按处理器个数复制多份,这样操作系统在绝大多数情况下,只需访问本处理器绑定的调度相关数据结构,就可用完成调度操作。这样在一个调度控制框架下就包含多个调度队列。当要把一个新进程或被唤醒的进程放入就绪队列时,操作系统可根据一些启发式方法(如随机选择某个处理器上的就绪队列或选择就绪进程数量最少的就绪队列)来放置进程到某个就绪队列。操作系统通过访问本处理器上的调度相关数据结构,就可以选择出要执行的进程,这样就避免了开销大的同步互斥操作。
小结
----------------------------------
多队列调度比单队列调度具有更好的可扩展性,多队列的数量会随着处理器的增加而增加,也具有良好的缓存亲和度。当多队列调度也有它自己的问题:负载均衡(Load Balance)问题。
考虑如下的例子,在一个有4个进程,两个处理器的计算机系统中,有两个就绪队列,PA和PB在就绪队列Q1,PC和PD在就绪队列Q2,如果采用基于轮转调度的多队列调度,那么两个处理器可以均匀地让4给进程分时使用处理器。这是一种理想的情况。如果进程PB结束,而调度不进行进一步的干预,那么就会出现PA独占处理器1,PC和PD分时共享处理器2。如果PA也结束了,而调度还不进行进一步的干预,那么(Load Imbalance)就会出现处理器1空闲,而处理器2繁忙的情况,这就是典型的负载不均衡(Load Imbalance)的现象了。这就没有达到轮转调度的意图。
所以多队列调度需要解决负载不均衡的问题。一个简单的思路就是允许进程根据处理器的负载情况从一个处理器迁移到另外一个处理器上。对于上面的例子,如果是处理器1空闲,处理器2繁忙的而情况,操作系统只需把处理器2上的进程分一半,迁移到处理器1即可。当如果是处理器1上运行了PA,处理器2上运行了PC和PD,这就需要统计每个进程的执行时间,根据进程的执行时间,让进程在两个处理器间不停的迁移,达到在一定时间段内,每个进程所占用的处理器时间大致相同,这就达到了轮转调度的意图,并达到了负载均衡。具体处理有多种方式,比如如下方式调度:
处理器1: A A C A A C ...
处理器2: C D D C D D ...
或者是:
处理器1: A C A A C A ...
处理器2: C D D C D D ...
当然,这个例子是一种简单的理想情况,实际的多处理器计算机系统中运行的进程行为会很复杂,除了并行执行,还有同步互斥执行、各种/O操作等,这些都会对调度策略产生影响。
小结
----------------------------------
本节对多种类型的计算机系统和不同类型的应用特征进行了分析,并给出了不同的性能指标,这些都是设计调度策略/算法的前提条件。我们给出了从简单到复杂的多种调度策略和算法,这些策略和方法相对于实际的操作系统而言,还很简单,不够实用,但其中的基本思想是一致的。如果同学们需要了解实际的操作系统调度策略和算法,建议阅读关于UNIX、Linux、Windows和各种RTOS等操作系统内核的书籍和文章,其中有关于这些操作系统的调度策略和算法的深入讲解。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册