- 多处理机三种模型
- 共享储存器多处理机
- 消息传递多计算机
- 广域分布式系统
多处理机的构造
- 高速缓存一致性协议
- 为了缓解多个DUP对总线的争夺,为每个CPU添加了高速缓存
- 如果CPU试图在一个或多个远程高速缓存中写入一个字,总线硬件检测到写,并把一个信号放到总线上通知所有其它的高速缓存。如果其他高速缓存有个"干净"的副本,也就是同存储器内容完全一样的副本,那么它们就可以丢弃该副本并让写在修改之前从存储器中取出高速缓存块。如果某些其它高速缓存中有“脏”副本(被修改的副本),它必须在处理写之前把数据写回存储器或者它通过总线直接传送到写者上
- 多处理机类型
- 每个CPU都有自己的操作系统
- 存储器划分成和CPU一样多的各个部分,为每个CPU提供其素有存储器以及操作系统的各自私有副本
- 优点是允许所有CPu共享操作系统的代码,而且只需要提供数据的私有副本
- 问题是很有可能出现负载不均匀的情况,并且可能多个cache同时被修改过,导致数据不一致
- 主从多处理机
- 一个主机运行操作系统,所有的系统调用都重定向到该CPU,剩下的CPU运行用户进程
- 含有单一个储存器
- 问题在于主CPU由于要处理所有的系统调用,可能过载,一般用于小型多处理机
- 对称多处理机
- 任何CPU都可以运行储存器上的操作系统,这是大多数现代多核处理器的组织形式
- 问题在于如果连个CPU同时运行相同进程或者请求同样的空前储存页面怎么办?
- 解决方法是用互斥量所处操作系统
- 由于操作系统的很多部分可以独立工作,所以可以单独锁住不同的临界区
- 每个CPU都有自己的操作系统
多处理机的同步
- 为了防止多CPU的竞争,必须在访问临界区的时候锁住总线
- 我在线程与进程那一章介绍的TSL指令就是用来实现互斥的
- TSL指令使用了自旋锁,当一个CPU锁住临界区的时候,别的请求CPU必须不断询
- 同时TSL指令还是一个写操作,每次一个询问都会使持有锁的CPU的cache失效
- TSL的锁变量虽然很小,但是每一次写操作都会使得整个cache页面失效,而持有锁的CPU很有可能会访问该锁变量周围的内存,于是cache不停被调入调出
- 解决方法是请求CPU先进行一个纯读操作查看锁是否空闲,只有空闲才会写
- 以太网二进制指数回退法
- 对于自旋锁的连续轮询对总线负载太大
- 该方法将一条延迟循环插在轮询之前,如果锁任然忙,加倍延迟时间,直到达到最大值
- 自旋与切换
- 对于单处理机,自旋锁没有意义,总是采用阻塞的方法
- 对于多处理机,除了自旋锁,还可以选择切换线程
- 但是切换的代价除了要保存当前状态,还可能导致cache失效,造成更多的缓存未命中
多处理机的调度
-
对于内核级线程,不仅要考虑接下来调度哪个线程,还要考虑由哪个CPU使用
-
分时调度
- 如果有 CPU 空闲则选择优先级队列中的最优先线程到此 CPU
- 智能调度
- 当一个线程持有自旋锁时,如果因为时间片用完而切换掉,等待自旋锁的CPU将会一直自旋
- 解决方法是当一个CPU持有自旋锁时,给与一个标志,使其不被自动切换掉
- 亲和调度
- 当线程A在某个CPU运行一段时间被切换后,当A重新开始运行时,最好还在该CPU,此时可以重用一些还存在的cache块
- 两级调度算法采用了这种观念,他使得每个CPU有自己的线程集
- 这种方法使得负载在各个CPU上大致平均分配了
-
空间共享
- 相互关联的一组线程(比如一个进程中的线程)同时调度
- 直到有大于等于线程数的CPU空闲才开始执行所有线程
- 减少了相关线程切换的开销,互相通信更方便
多计算机与分布式系统
- 分布式系统
- 分布式系统的每个节点都有自己的私有储存器,没够共享物理储存
- 每个节点可以运行不用的操作系统,因此缺少共同的底层模型和接口
- 分布式系统在底层网络上添加了一些通用的模型,称之为中间件,某种意义上是分布式系统的操作系统