苹果在2008 年4 月23 日,冒着极大风险硬着头皮发表初代iPhone 的隔年,耗费2 亿7,800 万美元,购并了专注开发高效能Power 处理器的PA Semi,组成其处理器研发团队的骨干,然后在2012 年9 月发表的iPhone 5,其心脏「A6」处理器,终于不再使用来自ARM 授权的核心,采用自家的「Swift」微架构(Micro Architecture)。
再以世界上首款抢滩登陆智慧型手机与平板的64 位元ARM 处理器「A7」(Cyclone 微架构)为起点,苹果自家SoC 开始逐渐展现压倒ARM Cortex 家族(与躺着中枪的Qualcomm 自有核心)效能优势,且随着时间演进,差距越拉越开。
接着,每代iPhone 发表后,各大科技媒体网站的报导,与底下的读者回应,只会有两种制式的单细胞生物反应:
文章高高挂着「众人都惊呆了,连开发效能测试软件的人都不知道发生了什么事」如内容农场般的标题,再来继续机械化的炒作「苹果会不会用自家芯片取代Intel处理器」的多年冷饭。
底下的读者留言鸡同鸭吵成一团,上演「Android 自由主义」和「苹果神权政治」信徒大对决,没有人讲到任何值得注意的重点,连一丝一毫的学理成分都没有,宗教信仰就是如此奇妙。
笔者不啰唆,直接在这里讲结论:
藉由牢牢把持软硬件平台的「封闭性」先天优势,苹果掌握了ARM 指令集迈向64 位元带来的机会,打造出一系列同时间能够有效处理更多指令的先进微架构。
看起来好像微言大义到接近废话的程度?如果你真的这样想,那你就更有继续读下去的必要。
近年来拜ARM 为首的授权IP 商业模式之所赐,越来越多人搞不懂这两者的差别,完全混在一起,这些年来笔者已经听过太多让人完全笑不出来的笑话,所以在此特别重述一次。
支配智慧型手机市场的ARM 又是怎么一回事呢?以32 位元ARMv7-A 指令集为例,在手机上常见的微架构(核心),总计有:
ARM 本家卖IP 授权给别人的Cortex-A5 / A7 / A9 / A12 / A15 / A17 这几种核心微架构。
Qualcomm 自行打造的Scorpio / Krait。
苹果并购PA Semi 后关起门来搞出的A6「Swift」,iPhone 5 的心脏。
换成64 位元ARMv8-A,就变成以下场景:
ARM 本家卖IP 授权给别人的Cortex-A35 / A53 / A57 / A72 / A73 这几种核心微架构。
增加半精度浮点支援和系统可靠度机能的ARMv8.2-A 指令集:Cortex-A55 / A75。
Qualcomm 自行打造的Kyro。
nVidia 的Project Denver。
苹果继续关起门来搞出的A7「Cyclone」,与之后的众多芯片,如A8「Typhoon」、A9「Twister」、A10「Fusion」(Hurricane + Zephyr)、A11「Bionic」(Monsoon + Mistra) 。
为了伺服器而量身订做的特殊微架构,如Qualcomm Centriq 2400 的「Falkor」,和Cavium Thunder X 系列的核心。
只要作业系统相同(如同版本Android 或iOS),这些核心微架构应当正确执行使用ARM 指令集撰写或编译出来的软件,讲的更专业或更假掰一点,它们拥有相同的应用程式二进位执行档介面(ABI,Application Binary Interface),如同Intel 与AMD 的x86 处理器都应可正确安装Windows 作业系统,理所当然执行Office 等应用软件和Battlefield 等套装游戏。
至于Qualcomm、苹果和nVidia,是否根本自身特殊需求,自行定义「非官方」ARM 指令,那就后头有空再讨论了。
在执行相同指令集「语言」的前提之上,相容处理器的效能要能够胜出,只有微架构设计能否比竞争对手有效处理更多的指令。方向不外乎:
更高的时脉:虽然往往计算机概论会教你「指令管线阶段越多,代表处理器同时执行更多的指令,只是这些指令位处于不同的阶段」,但实际上最多还是一个时脉周期「吐出」一个被执行完毕的指令,所以现实层面的「加深指令管线」,实际上跟「提高运行时脉」讲的是同一件事。很不幸的,智慧型手机因严格的功耗限制,透过积极追求高时脉以提高效能,是比较不切实际的方向。
更宽的管线:一个便当吃不够,你可以吃第二个,嫌执行一个指令不够看,你也可以同时执行第二个,这就是源自1966年CDC6600的「超纯量」(Superscalar)架构。另外也有纯软件方式、让编译器去一个萝卜一个坑塞指令到不同执行单元的「超长指令集」(VLIW),这就不在本文的讨论范围内了。
足以喂饱嗷嗷待哺执行单元的高效能记忆体子系统:包含系统主记忆体、快取记忆体、连结多个处理器核心的汇流排、举足轻重的快取记忆体资料一致性协定(Cache Coherence Protocol) ,甚至可以非循序的存取记忆体位址(Memory Disambiguation),都是不可或缺的「基础建设」。
但「指令管线化」与「指令执行平行化」也带来了新的挑战。
控制相依性:电脑有别于计算器的最重要特征在于「条件判断」的能力,根据不同的条件执行不同的指令流,处理器如碰到分支(Branch)或跳跃(Jump),就须改变指令执行的流程,清除已经进入管线的指令,从另一个记忆体位址撷取指令,重新执行并存取相关的资料(或称为「运算元」,意指运算的目标,如特定资料暂存器或记忆体位址),而具备条件判断的分支,造成的伤害更大,因为需要管线停下来等待其结果、或着事先预测并「先斩后奏」。
解决方案:分支预测(Branch Prediction),与后面会提到、釜底抽薪减少分支指令的「条件执行」(Conditional Execution)。
资料相依性:当同时执行多个指令,最忌讳遭遇「撞衫」同时存取相同的资料暂存器与记忆体位址,特别是当指令集定义可操作的资料暂存器越少,软件手段可以尽量排除的空间越少,发生的机率也越高。
解决方案:以暂存器重新更名机制(Register Rename)为中心的非循序指令执行(Out-Of-Order Execution)。
然后根据分支预测结果而先斩后奏「预测性执行指令」(Speculative Execution),是分支预测与非循序指令执行的结合体。总之,我们尽其所能的让管线「顺畅」的像生产线不停的运转,实现最高的指令执行效率。
理所当然的,指令管线越深,一旦「筊杯」失败,要复原管线并恢复指令执行的代价,也越像火烧摩天楼一样恐怖,这也是高时脉深管线近年来不太受欢迎的另类主因,因为现实世界的应用程式,其实有很多难以预测的分支行为,越高的「代价」,更意味着更差劲的「效能/功耗」比。
讲了那么多原理,苹果从来不公开自主微架构的技术细节,那该如何掌握他们追求高效能的设计方向?
2014 年初,当多数世人正「惊呆」A7 的64 位元与惊人的性能表现时,有人注意到苹果提交的LLVM 原始代码,不仅透露了微架构代号是「Cyclone」,更包含众多重要的规格参数:
指令发出宽度(Issue Width):6
非循序指令执行缓冲区(Reorder Buffer):192
记忆体载入延迟(Load Latency):4
分支预测错误代价(Misprediction Penalty):16(一般介于14~19)
在当时,这是非常惊人的规格,就算摆在今天也是同样骇人,可同时处理的指令是同时期ARM 核心足足两倍(即使64 位元的Cortex-A57 也只能3 个指令),非循序指令执行引擎的「深度」则是Intel Haswell 等级,指令管线深度则中规中矩的维持在16 阶这一般水准。
相信有些读者早已从其他网站看过相关的报导,但有个「江湖传言」倒是值得注意:部分开发iOS 应用程式的程式设计者,做了一些指令输出率的实验,察觉到「A7 一旦执行32 位元程式码,指令输出率就腰斩了」,这个「特性」一路延续到A10,直到A11 根本没有32 位元应用程式可执行为止。
后来苹果当然就没有继续「规格大放送」,Wiki上苹果处理器的规格表,一路从A7到A11,都是维持这些数字,有没有经过实测考验也不得而知,反正就大家一起无限回圈继续惊呆,苹果持之以恒的甩开和其他竞争者的差距。
唯一可以确定的是,笔者在自己的iPad Pro 9.7 吋A10X 上,透过配对简单指令,测出每个时脉周期可同时输出「4 个整数,2 个浮点,2 个记忆体载入」的可怕性能。此外,A10X 与A11 放弃第三阶4MB 快取记忆体,而以大型化第二阶8MB 取而代之,也暗示了苹果极可能在快取记忆体技术有了重大的突破,可兼顾高容量与低延迟。
A11?笔者没有iPhone 8 和iPhone X 可用,有机会再测测看。
让我们重新画出命案现场的人形粉笔圈,归纳出苹果的产品设计取向:
微架构以64 位元效能为优先设计考量。
既然行动处理器受制于低功耗需求,难以透过提高时脉追求效能,索性以「更宽」的指令管线取胜。
同时执行更多指令,代表要耗费更多心思去解决暂存器相依的问题。
更强力的非循序指令执行引擎。
寄望指令集本身就定义更多的资料暂存器,降低「强碰」机率。
让ARM 指令集迈向64 位元的ARMv8-A,并非只有「将整数逻辑暂存器宽度延长到64 位元」和「提供64 位元记忆体定址空间」这么简单,抛弃昔日专注于嵌入式应用的遗产,更加的简洁优雅,更利于打造高效能微架构,引领ARM 荣登高效能的天堂,是这次指令集改版最神圣不可侵犯的绝对使命。
ARMv8-A 修订项目极多,但就笔者的角度,除了取消「加速重建储存CPU 状态的Context Switch 相关机制」(一堆就今日观点实在很小家子气的技术),和简化例外处理与执行特权阶层外,最重大的改革,只有两项:
倍增通用暂存器(GPR)数量,这件事在当年AMD 让x86 迈向64 位元时也发生过,意义重大。
取消涵盖整套指令集的「条件执行」(Conditional Execution),这和前者互为表里,因为总算挤出了珍贵的指令编码空间去增加暂存器数量。
其中又称为「引述式执行」(Predicated Execution,或Guarded Exectuion)的后者,目的在于减少程式中的分支,指令集提供简单扼要的条件执行指令,一次做完所有事情。
直接举例比较快。原本一个简单的If-Then-Else 循序条件判断,会需要等待确认条件结果,或着强行进行分支预测,管线才会继续动作:
if condition
then do this
else
do that
就变成这样:
(condition) do this
(not condition) do that
有没有感觉简洁多了?讲的玄一点,条件执行的中心精神在于「将控制相依性转化为资料相依性」。
然后有鉴于过去的应用程式,在这种If-Then-Else 的条件判断中,有60% 都是资料搬移指令,这也是为何指令集「事后」扩充条件执行功能,如DEC Alpha、MIPS、甚至x86,都以「条件搬移」(Conditional Move)为主。
以Alpha 为例,其指令格式统一为cmovxx(xx 代表条件),一个简单的条件搬移:
beq ra, label // if (ra) = 0, branch to 'label'
or rb, rb, rc // else move (rb) into rc
可以透过新指令,简化如下:
cmovne ra, rb, rc
在ARMv8 之前,整套ARM 指令集每道指令,都包含了4 位元的条件码,必须符合「某个条件」才会执行指令。如条件成立,执行此指令并写回运算结果。反之,指令执行结果无效,或不予执行。
回到原点,条件执行的优点很明显:
加速实际条件判断的效率,因为实际上只要比较0 与1(Bitwise)。
减少简单条件判断的分支,可以提升指令平行化执行的潜力。这也是为何很多VLIW 指令集普遍支援条件执行。甚至定义存放引述码(Predicate)的专用暂存器,以因应更复杂多样的条件判断,如摊平回圈的软件管线(Software Pipeline)。
但为何ARM 要取消看似完美的条件执行?
占用4 位元指令编码,实在是太浪费了,所以用「条件选择」(Conditional Select)取而代之。
举个范例:「CSEL W1, W2, W3, Cond」,如条件符合,W2 暂存器资料搬移到W1,如非,就W3 到W1。缺点是会稍微增加程式码体积,但绝对划算。
提高打造高效能非循序指令执行引擎的复杂度,在管线前端就要「预锁」后面所需要的相关资源,也增加后方需要「更名」的暂存器,更不利提升时脉。
可确保处理器正确执行所有软件的指令集回溯相容性,是商业上的「资产」,但也是设计处理器微架构的「包袱」。
我们有非常充分的理由相信,苹果急着驱离「32 位元低阶应用程式」,就是为了其处理器全力针对64 位元最佳化造桥铺路,而A11 如此惊世骇俗的效能表现,除了它根本是纯64 位元处理器,所有电晶体预算都砸在提升效能的刀口上,没有其他合理的解释了(新的异质多处理器排程也有影响,但没那么绝对)。「就算」A11 具备32 位元相容性,其性能表现恐怕也仅聊胜于无,不足挂齿。
无独有偶,Qualcomm 企图抢攻伺服器市场的Centriq 2400,也是纯64 位元的设计,这就是ARM 制定64 位元指令集扩充时,最希望看到的结果:雨后春笋般的高效能产品。
关于这个「年经」(每年发表一支新iPhone)议题,笔者不会赌上爷爷的名誉做不负责任的推论,但只留下两个留待读者思考的问题:
苹果能否承担转移的成本,尤其当Mac 用户已非弱势族群的当下。
苹果是否仍希望「吸收」Windows PC 的使用者。
Mac 是否改用苹果自家芯片这档事,并不只是「效能够好」就可以一笔轻松带过的大哉问,请各位多多考量商业层面的因素。
最后,再重新贴出本文标题的答案:
「藉由牢牢把持软硬件平台的『封闭性』先天优势,苹果掌握了ARM 指令集迈向64 位元带来的机会,打造出一系列同时间能够有效处理更多指令的先进微架构。」
这「一体成形」的绝对优势,在可见未来的深度学习之路上,会更加的牢不可破,这就是苹果在iPhone 前景未明之际,就胆敢购并PA Semi 投资未来,所得到的丰硕成果,就算你不喜欢「果粉」,你也不能不佩服乔布斯的远见。
至于PA Semi 究竟干过哪些值得苹果冒险的好事,等以后有机会,再好好谈谈,如果真的还有机会。
(来源:台湾水电工协会)