引言

随着科技的发展,尤其是在嵌入式领域,高性能、低功耗的处理器成为众多厂商追逐的目标,但是由于技术和工艺的瓶颈,试图在单核处理器上达到这样的目标变得越发困难,于是人们提出了多核处理器的概念。多核处理器的核心思想是一个处理器中包含若干个核(或线程),所有核(或线程)之间共享 IO、Cache、内存等资源,对于这些资源的使用和分配由硬件来完成,用户无需关注细节,因此每个核(或线程)对于用户来说就好像一个独立的虚拟 CPU,从用户角度来看,这个虚拟 CPU 独占所有的外设资源。

目前比较流行的多核处理器的架构有下面几种:

(1)SMP(Symmetric Multi-Processor)

这种架构的处理器由多个核组成,每个核有自己独立的 Cache,所有核共享内存和 IO。

(2)SMT(Symmetric Multi-Thread)

这种架构的处理器的每个核由多个线程组成(此处的线程指的硬件线程,而不是我们所说的操作系统的线程概念),每个核下的所有线程共享寄存器、ALU(CPU 运算单元)、Cache、内存、IO 等资源,线程之于用户也像一个虚拟的 CPU。这种架构的最大优势在于线程和线程之间的切换很快,通常一个时钟周期内就能完成。

(3)NUMA(Non-Uniform Memory Access)

这种架构和前面两种的区别在于它不是简单的一个处理器,而是一个由多个处理器组成的系统,每个处理器作为一个结点在该系统中存在。对于内存、IO 等资源所有结点也是共享的。

目前比较流行的处理器架构大多都推出了多核处理器的产品,比如 Intel 的 X86 双核处理器、Freescale 的 PPC 多核处理器、SUN 的 SPARC 多核处理器、RMI 和 Cavium 的 MIPS 多核处理器等。

MIPS 这种架构诞生于 Standford 大学,它的名字含义有双重意义,一是 “Microcomputer without Inter-locked Pipeline Stages”,另一种是 “Millions of Instructions Per Second”,它设计思想的核心是采用多级指令流水线技术达到高效的处理速度,目前比较常用的 MIPS 采用5级流水线的技术。因其性能高效、结构简单,MIPS 被誉为 RISC(Reduced Instruction Set Computing) 家族中最优美的一款处理器架构。基于 MIPS 的多核处理器因为其低功耗、高性能从而在嵌入式市场得到了广泛的应用。

针对上述这些多核处理器的特点,Linux 提出了 Multi-Processing 的概念,它的调度器可以将操作系统的线程均分到各个核(或硬件线程)上去执行,以此达到并行计算的目的,从而也可以极大地提高系统的性能。

Spinlock 的思想

Linux 在推出了 Multi-Processing 之后,多核处理器的并行处理的能力得到了极大的发挥,但是这同时也带来了一个问题,并行执行势必就存在多个核同时访问共享资源的情况,如何能够保证一个核在访问共享资源时,该共享资源不会被其它核所改写呢?

我们没有方法去控制对共享资源访问的有序性,但是我们有能力对共享资源采用锁的保护机制,当某个共享资源被锁住时,只有获取该锁的 CPU 核能够操作共享资源,其余试图访问共享资源的 CPU 核只能够等待这个锁的释放,这就是在 Linux 中被称为 Spinlock 的自旋锁保护机制。

Spinlock 的设计思想是基于一种被称为 Test-and-Set 的机制,它的操作分为三部分:

(1)INIT

初始化 lock 值。示例如下:

lock := CLEAR;

2)LOCK

这个流程包括两部分:首先 CPU 核反复轮询 lock 值直到它处于空闲状态为止,然后利用 Test-and-Set 方式尝试设置该 lock 值,Test-and-Set 的操作可以描述成三步:

(a)读取 lock 值;

(b)设置 lock 值;

(c)检查 lock 值是否设置成功,如果在步骤 (a) 之后还存在别的对 lock 值的操作,说明存在有并发访问 lock 值的情况,则步骤 (b) 的 lock 值将不能设置成功,还需要回到步骤 (a) 重新执行这个流程。

示例如下:

while ((lock == BUSY) || (TestAndSet(lock) == BUSY));

(3)UNLOCK

释放 lock 值。示例如下:

lock := CLEAR;

MIPS 中 Spinlock 的实现

传统的 C 语言是无法实现 Test-and-Set 的机制的,因为它无法在多核之间建立一个交互的机制,因此 Test-and-Set 需要处理器给以相应的支持。以 MIPS 为例,它提供了 LL(Load Linked Word) 和 SC(Store Conditional Word) 这两个汇编指令来实现对共享资源的保护。

LL 指令的功能是从内存中读取一个字,以实现接下来的 RMW(Read-Modify-Write) 操作;SC 指令的功能是向内存中写入一个字,以完成前面的 RMW 操作。LL/SC 指令的独特之处在于,它们不是一个简单的内存读取/写入的函数,当使用 LL 指令从内存中读取一个字之后,比如 LL d, off(b),处理器会记住 LL 指令的这次操作(会在 CPU 的寄存器中设置一个不可见的 bit 位),同时 LL 指令读取的地址 off(b) 也会保存在处理器的寄存器中。接下来的 SC 指令,比如 SC t, off(b),会检查上次 LL 指令执行后的 RMW 操作是否是原子操作(即不存在其它对这个地址的操作),如果是原子操作,则 t 的值将会被更新至内存中,同时 t 的值也会变为1,表示操作成功;反之,如果 RMW 的操作不是原子操作(即存在其它对这个地址的访问冲突),则 t 的值不会被更新至内存中,且 t 的值也会变为0,表示操作失败。

SC 指令执行失败的原因有两种:

(1)在 LL/SC 操作序列的过程中,发生了一个异常(或中断),这些异常(或中断)可能会打乱 RMW 操作的原子性。

(2)在多核处理器中,一个核在进行 RMW 操作时,别的核试图对同样的地址也进行操作,这会导致 SC 指令执行的失败。

采用 LL/SC 指令实现 Spin_Lock/Spin_Unlock 的范例如下。

MIPS 的 Spin_Lock

对于 MIPS 的 Spin_Lock 操作,可以用如下的方式实现:

表1. Spin_Lock
 Spin_Lock(lockky)
again:
ll $t0,lockky
beqz $t0,again
li $t0,
sc $t0,lockky
beqz $t0,again
sync

Line 1:

lockKey 是共享资源锁,这是块能被多核所共享的内存地址,该值为0表示锁处于空闲状态,为1表示锁已经被某个核所获取,其余核若想获取它只能等待,以下对于 lockKey 的定义相同。

Line 3:

将 lockKey 读入t0寄存器中。

Line 4:

比较 lockKey 是否空闲,如果该锁不可用的话则跳转到 Line 1。

Line 5:

给 t0 寄存器赋值为1。

Line 6:

将 t0 寄存器的值保存入 lockKey 中,并返回操作结果于 t0 寄存器中。

Line 7:

判断 t0 寄存器的值是否为0,如果为0表示 Line 5 中的操作失败,则返回 Line 1 重新开始;如果为1表示 Line 5 中的操作成功。

Line 8:

Sync 是内存操作同步指令,用来保证 sync 之前对于内存的操作能够在 sync 之后的指令开始之前完成。

表 2. 实现$s4与$s0指向的值的原子交换
L:
addi $t0,$zero,$s4
ll $t1,($s1)
beq $t1,$zero,L
sc $t0,($s1)
beq $t0,$zero,L
add $s4,$zero,$t1

MIPS 的 Spin_Unlock

对于 MIPS 的 Spin_Unlock 操作,可以用如下的方式实现:

表 3. Spin_Unlock
Spin_Unlock(lockkey)
sync
sw zero, lockkey

Line 2:

给 lockKey 赋值为 0,表示这个锁被释放。

Spinlock 的不足和改进

Spinlock 在多核处理器中得到了广泛的运用,但是它也存在一些不足,特别是在对共享资源竞争很激烈的情况下,这种不足会带来很严重的后果。

(1)Spin_Lock 操作是不可重入的,在同一个核上如果在释放锁之前调用了多次 Spin_Lock,这将导致当前 CPU 核处于死锁状态,严重情况下会引起系统的崩溃。

(2)Spinlock 不能保证进程对共享资源访问的公平性和有序性,先申请锁的进程有可能反而在后申请锁的进程之后获取锁,严重时甚至可能导致某个进程长时间无法获取锁而处于饥饿状态。

(3)当 Spinlock 被用于保护共享内存时,对于并发读操作的保护是多余的,反而会降低系统性能。

为了解决 Spinlock 的上述不足,我们提出了以下的改进措施,有些措施已经在 Linux 中有所体现。

参考链接:https://www.ibm.com/developerworks/cn/linux/l-cn-spinlock_mips/index.html

Linux 的 Spinlock 在 MIPS 多核处理器中的设计与实现的更多相关文章

  1. 【DSP开发】硬件信号量在多核处理器核间通信中的应用

    硬件信号量在多核处理器核间通信中的应用 刘德保1,汪安民1,韩道文2 1.同方电子科技有限公司研究所,九江 332009:2.解放军电子工程学院 摘要: 在多核处理器的软件设计中,核间通信机制是关键所 ...

  2. 编程之美 1.1 让cpu占用率曲线听你指挥(多核处理器)

    [目录] 不考虑其他进程,cpu画正弦曲线 获取总体cpu利用率 获取多核处理器单个cpu利用率 考虑其他进程,cpu画正弦曲线 下面的程序针对多核处理器,可以设置让任何一个cpu显示相应的曲线(本文 ...

  3. [转帖]AMD、英特尔为何争相走向胶水多核处理器?真相在此

    AMD.英特尔为何争相走向胶水多核处理器?真相在此 胶水多核到底好不好?这个事不是简单一句话能说明的,今天的超能课堂里我们就来聊聊MCM胶水多核技术的过去及未来. 作者:孟宪瑞来源:超能网|2018- ...

  4. 让cpu占用率曲线听你指挥(多核处理器)

    编程之美 1.1 让cpu占用率曲线听你指挥(多核处理器) [版权声明]转载请注明出处 http://www.cnblogs.com/TenosDoIt/p/3242910.html  [目录] 不考 ...

  5. Linux 4.21包含对AMD Rome处理器中新的Zen 2架构重要的新优化

    导读 Phoronix的Linux爱好者报告说,Linux 4.21里包含对AMD Rome处理器中新的Zen 2架构重要的新优化.AMD新推出的7nm EPYC Rome芯片带来了一种全新的独特架构 ...

  6. 多核处理器基础SMP&AMP&BMP

    多核处理器也称片上多核处理器(Chip Multi-Processor,CMP). 1.多核处理器的流行 多核出现前,商业化处理器都致力于单核处理器的发展,其性能已经发挥到极致,仅仅提高单核芯片的速度 ...

  7. [py]你真的了解多核处理器吗? 了解多线程

    越来越多的人搞爬虫,设计到多线程爬取, 还有一些机器学习的一些模块也需要这玩意, 感觉自己不会逼格不高. 抽时间赶紧玩一玩这东西, 希望提高对软件的认知和归属感,不要太傻. cpu内部架构参考 你知道 ...

  8. arm处理器中a5 a8 a9,v6 v7,arm7 arm9 arm11都是依据什么来分类的【转】

    转自:http://blog.csdn.net/maochengtao/article/details/9951131ARM处理器发展这么多年,有很多架构,很多不同的内核 架构有armv1 v2 v3 ...

  9. Python如何利用多核处理器

    Python中,如果想使程序充分利用多核处理器,有以下几个方案: l 使用threading模块,然后将程序运行在IronPython或Jython之上. l 使用Python自带的multiproc ...

随机推荐

  1. Tju 4119. HDFS

    4119.   HDFS Time Limit: 5.0 Seconds   Memory Limit: 5000KTotal Runs: 225   Accepted Runs: 77 In HDF ...

  2. HDU2255 奔小康赚大钱 —— 二分图最大权匹配 KM算法

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2255 奔小康赚大钱 Time Limit: 1000/1000 MS (Java/Others)    ...

  3. 连通图(Tarjan算法) 专题总结

    一.题目类型: 1.有向图的强连通分量: POJ1236 Network of Schools HDU1269 迷宫城堡 2.割点 & 割边: UESTC - 900 方老师炸弹 UVA315 ...

  4. 区块链共识算法 PBFT(拜占庭容错)、PAXOS、RAFT简述

    共识算法 区块链中最重要的便是共识算法,比特币使用的是POS(Proof of Work,工作量证明),以太币使用的是POS(Proof of Stake,股权证明)使得算理便的不怎么重要了,而今PO ...

  5. 【Bitset】 BZOJ4810

    难得学习一下C++的库..[至今连map,vector都没用过的我.. 首先#include<bitset>或<bits/stdc++.h> 定义函数:  { bitset & ...

  6. bzoj 2962 序列操作 —— 线段树

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2962 维护 sum[i] 表示选 i 个的乘积和,合并两个子树就枚举两边选多少,乘起来即可: ...

  7. 洛谷 P1344 追查坏牛奶Pollutant Control —— 最小割

    题目:https://www.luogu.org/problemnew/show/P1344 就是求最小割: 但是还要边数最小,所以把边权都*1001+1,这样原来流量部分是*1001,最大流一样的不 ...

  8. c#网格控件,Excel控件

    http://www.grid2000.com/images.html   Cell Type FlexCell supports following cell types: TextBox, Com ...

  9. python名片管理系统

    1.代码: (1)主程序 #!/usr/bin/env python # -*- coding: UTF-8 -*- import cards_tools # 无限循环,由用户主动决定什么时候退出循环 ...

  10. light oj 1032(数位DP)

    求一段区间中,每个十进制数所对应的二进制数中连续的1的个数之和. 设dp[i][0]代表长度为i的二进制数,首位为0,所含有的连续的1的个数之和. dp[i][1]代表长度为i的二进制数,首位为1,所 ...