ARM big.LITTLE
移动 SoC 如何平衡”高性能”与”长续航”这对根本矛盾?本文从 ARM big.LITTLE 的硬件架构出发,逐一拆解 Cluster 迁移、CPU 迁移、Global Task Scheduling 三种软件执行模型和五种任务迁移机制,完整揭示操作系统调度器在异构核心间做决策的底层逻辑。
1. 移动处理器的性能与功耗悖论
现代移动软件栈对处理器提出了相互矛盾的双重需求:一方面,游戏、视频渲染等场景需要极高的峰值性能;另一方面,音频播放、后台同步等低强度任务必须极度省电。传统设计的困境在于:单一微架构处理器不可能同时满足高性能和高能效这两端。用高性能核处理低强度任务会白白浪费能量、缩短电池续航;而在高性能场景中,核心又受制于热约束(thermal bounds)无法持续运行在最高频率。
ARM 给出的答案是 big.LITTLE 技术——将高能效”LITTLE”核心与高性能”big”核心耦合在同一系统中。它属于异构多处理(Heterogeneous Multi-Processing, HMP)的一种实现。
AMP, SMP和HMP的对比如下:
| 特征 | AMP (Asymmetric Multi-Processing) | SMP (Symmetric Multi-Processing) | HMP (Heterogeneous Multi-Processing) |
|---|---|---|---|
| 核心类型 | 可以完全不同 | 完全相同 | 不同性能等级(big + LITTLE) |
| 指令集兼容性 | 可以不同(如 Cortex-A + Cortex-M) | 一致(同一 ISA) | 100% 一致(通常同为 ARMv8-A) |
| 核心能力 | 差异很大 | 等价 | 有性能差异 |
| Cache 一致性 | 通常不要求(也可能有) | 必须支持一致性 | 通常全部核心在同一一致性域内 |
| 操作系统 | 每个核心可能运行独立 OS | 所有核心运行同一 OS 镜像 | 所有核心运行同一 OS 镜像 |
| 调度方式 | 静态分配,软件决定任务在哪个核 | OS 自动负载均衡 | OS 根据性能/功耗选择核心 |
| OS 视角 | 多个独立执行单元 | 多个等价 CPU | 多个能力不同的 CPU |
| 典型场景 | Cortex-A + Cortex-M | 8× Cortex-A53 | 4× Cortex-A53 + 2× Cortex-A73 |
| 任务迁移 | 通常不迁移 | 任意迁移 | 可以迁移,但需考虑代价 |
| 主要目标 | 分工协作 | 提升吞吐 | 平衡性能和功耗 |
核心前提是简洁的:big 和 LITTLE 共享相同的 ISA,软件同一份二进制可在两类核心上不加修改地运行。操作系统根据性能需求将线程动态分配到 big 或 LITTLE 核上——需要峰值性能时运行在 big 核上,其余大部分时间在 LITTLE 核上执行。
要理解操作系统如何做出这个”该用大核还是小核”的决策,我们必须先从硬件层面的耦合方式入手。
2. big.LITTLE 系统的物理架构
要理解操作系统调度器如何在 big 和 LITTLE 核心之间迁移任务,必须先了解底层硬件的三项基础设施:两种核心的 ISA 一致性如何保证软件兼容、Cache 一致性如何让数据迁移透明高效、以及中断控制器如何让中断在异构核心间自由路由。这三者分别对应软件兼容性、数据通路和事件分发——缺一不可。
2.1 核心组成与 ISA 一致性
big.LITTLE 系统中的两类核心共享相同的指令集架构(ISA),差异仅在于内部微架构——这种微架构层面的设计取舍赋予了它们截然不同的功耗和性能特征。所有核心硬件 Cache 一致,同一份应用二进制不经修改即可在任一类型核心上运行。
典型的配置以 Cortex-A7 作为 LITTLE 簇、Cortex-A15 作为 big 簇。LITTLE 簇负责处理音频播放、页面滚动、OS 事件等低强度、常驻后台的任务,big 簇则在游戏、视频处理等场景下投入运行。
2.2 硬件 Cache 一致性:CCI-400 的角色
在 big 和 LITTLE 簇之间迁移任务时,数据必须透明且高效地转移。如果缺乏硬件一致性支持,跨簇数据传输只能经过主存——这在速度和功耗上都是灾难,而且需要复杂的 cache 维护软件来保证数据正确。
ARM 通过 CoreLink CCI-400(Cache Coherent Interconnect)提供硬件一致性支持。CCI-400 实现了 MOESI 协议,使得大数据可以直接在参与核心的 L1 Cache 之间传输,无需经主存中转。
2.3 共享中断控制器:GIC-400
除了数据一致性,中断路由也是异构系统必须解决的硬件问题。当中断可以在任意核心上触发时,迁移中断目标核心需要:
- CoreLink GIC-400(Generic Interrupt Controller):支持中断在选定的任意核心间迁移
- 所有核心可以通过分布式中断控制器互相发信号
任务切换完全由 OS 调度器处理,对应用程序透明。
硬件提供了 Cache 一致性和中断可迁移性这两个基础能力。在此基础上,软件如何组织两类核心的协同工作,便有了三种不同的执行模型。
3. 三种软件执行模型
ARM 将 big.LITTLE 的软件执行模型分为两大类:迁移(Migration)和全局任务调度(Global Task Scheduling)。其中迁移模型又可以细分为 Cluster 迁移和 CPU 迁移。
理解迁移模型的关键类比是 DVFS(Dynamic Voltage and Frequency Scaling)——迁移行为本质上可视为 DVFS 操作点过渡的自然延伸:负载增加时沿当前核心的 DVFS 曲线上行,当当前核心(或簇)达到最高操作点仍不够时,触发核心(或簇)迁移,在新的 DVFS 曲线上继续遍历操作点。
这种设计将迁移泛化为 DVFS 系统的一个高阶操作点——设计哲学上与已有电源管理框架完全兼容。
3.1 Cluster 迁移
Cluster Migration 是早期 big.LITTLE 系统采用的一种运行模式。在任意时刻,系统只选择一个簇(big 或 LITTLE)作为主要计算簇运行,另一个簇处于关闭或非调度状态。只有在簇切换的短暂过程中,两个簇可能同时处于过渡状态。
软件栈大部分时间运行在 LITTLE 簇上,仅在需要峰值性能时切换至 big 簇。这种模式要求两个簇具有相同数量的核心,因为切换过程本质上是两个对等 cluster 之间的整体替换。
Cluster Migration 的主要缺陷是无法处理非均衡负载。当簇内只有一个核心负载较高,而其他核心处于空闲状态时,Cluster Migration 仍然会进行整个簇级别切换,导致不必要的性能和功耗开销。
实例:非均衡负载导致的”过度升级”
1 | 场景:4 核 LITTLE 簇,其中一个核心运行视频解码(高负载),其余核心空闲 |
3.2 CPU 迁移(In Kernel Switcher)
CPU 迁移将粒度从”簇”细化到”核心对”:每个 big 核心与一个 LITTLE 核心组成一对。在任意时刻,每对中只有一个核心处于活跃状态,另一个核心被关闭或保持低功耗状态。
在 Linaro In Kernel Switcher(IKS)实现中,操作系统看到的是若干个逻辑 CPU,每个逻辑 CPU 的底层物理实现可以根据负载需求,在 big 和 LITTLE 核心之间切换。
与 Cluster 迁移的关键区别:
| 维度 | Cluster 迁移 | CPU 迁移 |
|---|---|---|
| 活跃核心 | 同一时刻只有一个簇工作 | 不同核心对可分别选择 big 或 LITTLE |
| 拓扑支持 | 通常要求核心数量对称 | 支持非完全对称拓扑 |
| 粒度 | 整个簇 | 单个核心对 |
| 代表实现 | — | Linaro In Kernel Switcher (IKS) |
实例:3+2 非对称拓扑下的 CPU 迁移
1 | 配置:2 个 big 核(Cortex-A15),3 个 LITTLE 核(Cortex-A7) |
然而,CPU 迁移的一对一绑定约束限制了核心利用率:同一个核心对中的 big 和 LITTLE 不能同时运行。当 big 和 LITTLE 数量不匹配时,多出的核心无法参与迁移配对,无法获得异构切换带来的性能收益。
3.3 全局任务调度 (GTS)
ARM 将 big.LITTLE 的软件模型从早期的簇级迁移模型逐步演进到全局任务调度(Global Task Scheduling,GTS)。GTS 是 ARM big.LITTLE MP(Multi-Processing)方案中的核心调度思想。
GTS 的核心突破在于:
操作系统调度器开始感知 big 和 LITTLE 核心之间的计算能力差异,而不是将所有 CPU 视为同等性能的处理单元。
它通过统计线程运行历史和负载变化,估计每个线程的性能需求,并据此决定线程应该运行在哪类核心上。
例如:
Cortex-A15 大核的单线程性能高于 Cortex-A7 小核。调度器通过维护不同核心的性能容量信息,将线程负载转换为统一的容量指标:
1 | 线程负载需求 |
这样,调度器可以判断某个线程更适合运行在 LITTLE 核心还是 big 核心,而不是简单根据固定阈值进行核心切换。
GTS 相对迁移模型的三大优势:
- 拓扑自由:big 和 LITTLE 核心数量可以任意不等
- 全核心利用:当需要峰值性能时,所有核心(big + LITTLE)可以同时上线
- 隔离执行:可将 big 簇专用于计算密集型线程,LITTLE 簇处理后台服务和中断——这使得重量级计算任务能更快完成,因为没有额外的后台线程干扰。
中断也可以被定向到特定类型的核心——将高频系统中断绑定到 LITTLE 核,避免打断 big 核上的持续计算。GTS 确定了”按线程负载分配核心”的调度哲学,但具体的分配决策如何落地?big.LITTLE MP 通过五种不同场景触发的迁移机制来回答这个工程问题。
4. 五种任务迁移机制
big.LITTLE MP 调度器的根本任务是决定:每个软件线程应该运行在 LITTLE 核心还是 big 核心上。
4.1 迁移阈值
调度器通过比较每个线程的跟踪负载(tracked load)与两个可调阈值来做出迁移决策——上迁移阈值和下迁移阈值。
- 上迁移阈值(up migration threshold):当前运行在 LITTLE 核心上的线程,其跟踪负载超过此阈值 → 判定为应从 LITTLE 迁移到 big
- 下迁移阈值(down migration threshold):当前运行在 big 核心上的线程,其跟踪负载低于此阈值 → 判定为应从 big 迁移到 LITTLE
这两个阈值之间存在明显的滞后(hysteresis)间隙——如上迁移阈值为 80%、下迁移阈值为 20%。这种设计防止了负载在阈值边界附近波动时引发频繁的迁移振荡(ping-pong effect)。当一个线程的负载从 79% 升到 81% 再降到 79% 时,如果没有滞后间隙,调度器会在两个核心之间来回迁移该线程——每次迁移都伴随着上下文保存/恢复和 cache 重新填充的开销。
同一簇内则适用标准的 Linux 调度器负载均衡——将负载均匀分散到簇内各核心;跨簇迁移则由 big.LITTLE MP 调度逻辑负责。
4.2 DVFS 感知的负载跟踪
跟踪负载并非简单的运行时间统计。它被设计为与 DVFS 频率变化协同工作:调度器会根据当前核心频率对负载进行归一化(frequency invariance),尽量消除频率变化对负载估计的影响。这避免了线程因核心降频而被错误地判定为”轻量”,使得 big.LITTLE MP 与 DVFS 能够协同工作。
4.3 Fork 迁移
当创建新的任务(如通过 fork() 或 clone())时,没有历史负载数据可供参考。系统默认将新任务放置在 big 核心上,以降低高负载任务首次运行的响应延迟;如果后续判断其负载较低,再通过 Wake 迁移快速下迁至 LITTLE 核。
三类任务的行为差异:
- 持续低强度任务(如 Android 系统服务):仅在创建时短暂运行在 big 核上,随后快速下迁至 LITTLE 核,几乎无额外开销。
- 持续高强度任务:从 big 核启动,后续持续运行在 big 核——避免了”先在小核启动再迁移”的惩罚。
- 间歇性高强度任务:从 big 核启动,大多数调度周期保持在 big 核上,利用 big 核的加速优势。
4.4 Wake 迁移
当任务从睡眠中被唤醒时,调度器需要选择将其放置在哪个簇上。核心机制依赖于跟踪负载的睡眠不变性:负载指标在睡眠期间冻结在最后一次运行时的值。因此,周期性繁忙的任务唤醒时总是倾向于分配在 big 核心上——只有任务真正改变其行为模式,在后续运行中以明显更低的计算强度执行,其跟踪负载才会逐步降低,最终触发下迁移。
- 睡眠期间负载指标冻结在最后一次运行时的值
- 周期性繁忙的任务(睡眠 → 唤醒 → 计算 → 睡眠)始终保持高负载指标
- 这些任务唤醒时自然会被分配到与上次运行相同的簇——在 Fork 默认放 big 且高负载不触发下迁的前提下,相同簇通常为 big 核
- 关键约束:上迁优先选择空闲的 big 核,以避免影响已经运行在大核上的高负载任务;下迁则不存在这一限制,可直接迁移至负载较低的 LITTLE 核
- 只有任务真正改变其行为模式——长期减少计算量——其跟踪负载才会随时间衰减到触发下迁移阈值
主要说的是,睡眠期间跟踪负载不变,睡眠唤醒时用的是睡眠之前的值。
4.5 Forced 迁移
Fork 和 Wake 迁移都依赖”任务会偶尔睡眠”这一前提——在睡眠边界上产生调度点。但对于长期运行且从不睡眠的计算密集型任务,这两个机制无法生效。Forced 迁移通过定期检查来弥补这一盲区:调度器周期性地扫描每个 LITTLE 核心,如果发现任务跟踪负载超过上迁阈值,则将其迁移到空闲的 big 核心。这是一种主动的推(push)机制——由 LITTLE 核心端主动将过载任务推送至 big 核心,不依赖任务自身的睡眠行为。
4.6 Idle Pull 迁移
当 big 核心空闲时,Idle Pull 机制会主动搜索 LITTLE 核心上的高负载任务:检查所有 LITTLE 核心上是否有任务的负载超过上迁阈值——如果有,则将其迁移到空闲的 big 核心。如果没有找到合适的任务,big 核心则直接断电。这保证了 big 核心在活跃时始终承担系统中计算最密集的任务,big 核在空闲时则断电避免空转浪费能源。这种”大核作为加速器”的定位是 big.LITTLE MP 效能优势的关键来源。
4.7 Offload 迁移
GTS 默认不会像同构 SMP 那样进行跨簇负载均衡——这防止了轻量任务被分散到 big 核上。但副作用是:高负载任务会集中在 big 核,LITTLE 核可能空转而未被充分利用。Offload 迁移周期性地检查 big 核上的任务:将那些跟踪负载低于下迁移阈值的任务向下迁移到 LITTLE 核,利用 LITTLE 核的闲置算力。关键约束:下迁的任务仍然是上迁移的候选对象,如果下一次调度检查时负载回升超过上迁阈值,会被重新标记为上迁候选。
4.8 五种迁移机制协同全景
| 机制 | 触发源 | 方向 | 特点 |
|---|---|---|---|
| Fork 迁移 | 新线程创建(fork()) |
→ big | 默认上迁;轻量线程后续自然下迁 |
| Wake 迁移 | 线程从睡眠中唤醒 | 保持或按负载迁 | 负载指标睡眠期间冻结 |
| Forced 迁移 | LITTLE 核周期性 tick 检查 | LITTLE → big(推) | 弥补无睡眠线程的盲区 |
| Idle Pull 迁移 | big 核空闲 | LITTLE → big(拉) | 大核即时空闲利用 |
| Offload 迁移 | 周期性反向检查 | big → LITTLE(推) | 防止小核算力闲置 |
这五种机制覆盖了从线程创建、唤醒、长运行到核心空闲所有关键状态转换——形成一个完整的决策闭环。那么,这套机制在实际硅片上能带来多少能效收益?ARM 在真实平台上的测试数据给出了量化的答案。
5. 实践效果与软件生态
前面五章从硬件架构到调度器算法,完整呈现了 big.LITTLE MP 的工作链路。本章聚焦于它的实际交付——在真实工作负载下的功耗和性能数据,以及开发者如何获取并集成这套方案。
5.1 能耗与性能数据
ARM 在典型使用场景下测试了 big.LITTLE MP 相对于纯 Cortex-A15 系统的表现。比较对象是 四个 LITTLE 核心 + 四个大核心组成的 big.LITTLE 系统” vs 仅由四个大核心组成的系统。
能耗表现:
Benchmark:
- 线程数较多(>4)时:big.LITTLE MP 可以同时利用 big 和 LITTLE 核心,提高可用计算资源。
- 当 big 核心繁忙时,Offload 迁移会将部分计算密集型任务分散到 LITTLE 核心。
- 当 big 核心空闲时,Idle Pull 迁移会优先利用 big 核心作为性能加速器。
- 线程数较少时:big.LITTLE MP 至少不会降低性能,通常还有小幅提升。原因是调度器可以让 big 核心专注运行高强度任务,避免被低负载系统服务或频繁中断干扰。
5.2 与 DVFS 和电源管理的集成
big.LITTLE 并非孤立技术。它与核心电源管理框架深度集成:
- 核心断电:未使用的核心可以单独断电;若某簇中全部核心关闭,整个簇本身可以断电
- DVFS 协同:DVFS 感知的负载跟踪确保 big.LITTLE MP 和 DVFS 和谐工作
- PSCI 接口:通过电源状态协调接口(PSCI),迁移操作可以在多特权级 OS 之间协调进行
5.3 传统对称多处理的对比
| 维度 | 传统 4×big SMP | 4×big + 4×LITTLE HMP |
|---|---|---|
| 峰值性能 | 4 个大核 | 8 个核心同时上线的潜力 |
| 低负载功耗 | 4 个大核均需上电 | 仅 LITTLE 核活跃,big 核断电 |
| 后台任务干扰 | 后台服务占用大核算力 | 后台隔离在 LITTLE 核 |
| 热约束 | 大核长时间运行易触碰热墙 | 负载分流避免单个簇过热 |
6. 关键要点
以下九条要点从硬件基础、调度演进到电源管理,总结了 big.LITTLE 异构多处理的核心思想,可作为理解和评估异构架构的检查项。
big.LITTLE 解决性能与能效的矛盾
单一微架构难以同时满足移动设备”峰值性能 + 持续低功耗”的需求。big.LITTLE 通过组合高性能 big 核和高能效 LITTLE 核,在不同负载阶段选择合适的计算资源;HMP 进一步支持两类核心同时参与调度。
硬件 Cache 一致性是任务迁移的基础
没有 CCI-400 等硬件一致性支持,big 和 LITTLE 核之间迁移任务需要频繁访问主存,导致延迟和功耗增加。硬件一致性使任务迁移对软件更加透明。
迁移机制是 DVFS 的扩展
DVFS 通过调整频率改变计算能力,而 big.LITTLE 在此基础上增加了”切换核心类型”这一维度。当当前核心升频仍无法满足性能需求时,任务可以迁移到更强的核心。
CPU Migration 比 Cluster Migration 更灵活
Cluster Migration 以整个簇为单位切换,粒度较粗;CPU Migration(如 IKS)允许 big 和 LITTLE 核混合运行,提高资源利用率。但早期一对一绑定仍限制了扩展性。
GTS/big.LITTLE MP 实现真正异构调度
GTS 让调度器直接感知不同核心的计算能力,不再依赖固定 big-LITTLE 配对关系,使任意核心都可以参与任务调度,充分利用异构资源。
五种迁移机制覆盖线程生命周期
- Fork:创建任务时选择核心
- Wake:唤醒任务时重新评估
- Forced Migration:运行过程中主动迁移
- Idle Pull:空闲核心主动获取任务
- Offload:高负载核心卸载任务
五种机制共同形成动态负载均衡闭环。
DVFS 感知负载跟踪避免调度误判
频率变化会影响 CPU 实际计算能力,因此不能直接使用原始利用率判断负载。结合当前频率进行负载归一化,可以避免降频导致的负载低估。
睡眠期间冻结负载避免任务抖动
对于音频、视频等周期性任务,睡眠期间保持已有负载状态,可以避免线程频繁迁移;只有任务行为真正变化时才重新触发调度。
big.LITTLE 与电源管理深度结合
异构调度不仅决定任务运行位置,也管理硬件资源状态。空闲核心和簇可以进入低功耗状态,并通过 PSCI 等接口协调 CPU 上下电和迁移。