泡泡网CPU频道1月26日 原文标题为《轻松读懂“应用处理器”微架构 2013 版》,对不起,你被标题欺骗了,实际上对许多读者来说要读懂本文并不是那么轻松:p 随着半导体工艺的日趋先进,智能手机(Smartphone 或者 Superphone)、平板电脑(Tablet 或者 Pad)已经成为许多网友最常使用、最多关注、更新最快的电子消费产品,高度便携性是这类产品的最关键成功原因。 所谓便携性自然是指产品必须足够轻便而且需要有足够的续航能力,因此这就要求产品的原件必须足够省电,只有这样才能减少散热和电池体积这两个最占体积和重量的问题。 要达到这个目标,肯定要做功能和性能上的妥协,至少相对个头更大的笔记本电脑、台式机而言,像降低吞吐率或者增加时延,从实测性能而言,目前智能手机或者平板电脑的 CPU、图形处理器性能基本上相当于 6 到 10 年前台式电脑的水准。 举个简单的例子,在俄罗斯网站 ixbt 的讨论区上,有这样的一条帖子,一位名为 ssvb 的网友采用 origenboard.org 的一片 Samsung Exynos 4210 开发板(配有 Exynos 4210 处理器具备两个 ARM Cortex-A9 处理器内核)跑出来的 High Performance Linpack (HPL)性能是 1.307 GFLOPS,同贴中还有 Intel Atom N450(Pineview 架构,45nm,单核) 1.66GHz 的测试结果——0.944 GFLOPS 以及 Cortex-A15 1.7GHz 双核 HPL 为 4.3 GFLOPS。 NVIDIA 官网上的一份 SC011 文件也表明 Tegra 2(ARM Cortex-A9 双核 1GHz,理论双精度浮点性能 2GFLOPS)的 HPL 性能为 1.15GFLOPS( 57% 效率,200MFLOPS/瓦) 。 这都是一个什么概念?我曾经在 06 年的时候用 Pentium D 820 2.8GHz 跑出来的 HPL 性能为 10.12 GFLOPS,Athlon64X2 2.6GHz 为 9.158 GFLOPS。 那么现在台式机的 HPL 性能状况如何? 在去年我用 Core i7 2600K 3.4GHz 配合未支持 AVX 指令的 GotoBLAS(数学库)上得到的 HPL 性能为 51.18 GFLOPS 左右,后来又用支持 AVX 的 OpenBLAS(原 GotoBLAS 开发者停止更新后的其中一个后续开源社区版)得出的 HPL 性能为 99.38 GFLOPS,到 2013 年支持 AVX2 指令集的 Haswell 架构出来后,这个测试结果应该还能接近再翻番,达到 200 GFLOPS 级别。 也许你会说手机、平板要双精度干啥呢?请不要忘记在 30 年前的 x86 处理器根本没有集成任何硬件浮点单元,现在的情况又如何?曾经做出号称最强 x87 协处理器的 Cyrix 后来一头扎进整数为王的产品策略后现在影都没了。 “干啥”这个问题往往是硬件具备并达到一定性能条件后就会有答案的,台式机上的性能测试软件和方案会随着手机、平板性能日益强大而变得在这类设备上运行也理所应当,除了上面说的 HPL 外,各类 PC 上流行的测试工具例如 SPEC CPU20xx、3DMark 等也会是如此。 传统的 CPU 性能测试的确不能完全适用于手机、平板的 SoC 芯片(人们把可以在移动操作系统上跑应用软件的 SOC 称作应用处理器,简称 AP),但是请注意我说这句话是因为 SoC 并不仅仅有 CPU,还有 GPU、音视频编解码器、存储控制器、非易失性存储单元、数模/模数转换器以及各种输入输出周边等,这使得我们要单纯评价一款 SoC 是否最佳的时候可能会感到颇为伤神。 话虽如此,不过总的来说,SoC 中和性能最密切相关的依然是 CPU、GPU,因为智能设备里几乎所有程序的运行都必须依仗两者来执行,与用户的使用感受有直接关系(请注意,我们这里说的只是指 SoC 芯片中,而非手机或者平板电脑整体)。因此,纵然手机、平板处理器型号各异并且内中千头万绪,我们还是应该从大家最关心的 CPU、GPU 着手来了解。 现在情况简单多了,按照 ISA(指令集架构)划分,因为目前的手机、平板 CPU 无非是 ARM、Intel/AMD 两大阵营,潜在的还有 MIPS,不过目前 MIPS 似乎在这个领域还成不了气候,更像是一个备胎。 如果你对计算机科学还不是很了解的话,对 ISA 这个词可能也不会很了解,虽然它经常出现在一些时髦的技术文章中。 电脑显然并不能直接明白 C、Java、Basic 这样的高级语言(虽然有人尝试过开发高级语言处理器,但是无不失败告终),搭建在高级语言和 CPU 本机代码之间的就是 ISA。 ISA 的全称是 instruction set architecture,中文就是指令集架构,有时候直接称呼为架构(architecture),是指程序员实际“可见”的指令集,包含了程序员编写一个能正确运行的二进制机器语言程序的所有信息,涉及到指令、 I/O 设备等。例如 Intel 的 IA-32、Intel 64(曾经名为 IA32e、EM64T 等);ARM 的 ARMv7、ARMv8 等等。 这里的 IA32、Intel 64 或者 ARMv7、ARMv8 其实是指各自指令集架构的不同版本,有时候我们嫌啰嗦,所以把前两者统称 x86,后两者统称 ARM。 将 ISA 变成真正可以使用的实物需要经过“实现”,它包括两个层面:组成和硬件。 组成是从计算机设计的高阶层面而言,例如:存储系统、存储互连接、CPU(包括算术、逻辑分支、数据传输的实现)设计,有时候“组成”又被称作微架构(microarchitecture),英特尔 Nehalem、NVIDIA Kepler、ARM Cotrex-A57 都可以属于各自某系列芯片的微架构,其中 Kepler 的 ISA 是 CUDA PTX 和 Cortex-A57 的 ISA 属于 ARMv8。 硬件通常是指电脑的规格,包括具体的逻辑设计、封装技术,同一系列的产品可能有相同的 ISA、近乎一样的微架构,但是存在某些具体规格的差别,例如 NVIDIA Tegra 3,有 AP30、AP33、T30、T33、T30S、T33S、T30SL 等具体的型号,它们都属于 Tegra 3 微架构,但是频率规格、内存规格等地方都有差别。 而 GPU 方面则复杂一些,有 PowerVR、高通、NVIDIA、ARM、Intel 等等,其中使用最广泛的就是 PowerVR,这得益于 PowerVR 10年前就决定全面切换到移动设备上,铺桥搭路的功夫很扎实,而 NVIDIA 和 Intel 的商业模型都是只用于自家产品(当然 NVIDIA 也曾经在游戏机领域做过 RSX 这样的 IP core 授权)的,所以目前未能在其他 SoC 上看到。 下面的表格给出了这两年来比较热门的手机或者平板电脑 ARM 处理器,它们基本上都被应用于各公司的旗舰级产品中。
它们都属于 ARMv7 架构,架构寄存器数量为 16 个,其中 Tegra 2/3、Exynos、A5/A5X 的 CPU 核心是 Cortex A9 或者 Coretx A15,都是来自于 ARM 的 IP core 授权,而 A6/A6X 的 Swift 和高通的 Scorpion/Krait 则分别是苹果和高通获得 ARM 架构授权后而各自自行开发的。 众所周知,IP core 的全称是 Intellectual Proerty core,意即知识产权内核,是目前各种嵌入式应用、个人智能消费类设备中最为常见技术类型,数十亿计的产品都采用了来自 ARM、MIPS 的 IP core。IP core 被设计成可以和芯片中其他逻辑单元(例如视频编解码器、I/O 界面、内存界面)协同运作形成一枚可以支持特定应用的处理器。 IP core 分为两类:硬核(hard core......不要会错意了)和软核(soft core)。硬核是针对特定半导体厂商而优化的,对外人来说是一个提供了外部界面、不修改的“黑盒子”,获得授权的厂商通常只能对核外的逻辑参数进行修改,例如 L2 cache 大小,但是 IP core 本身不可修改。而软核的设计代码则是可以针对不同半导体厂商做编译和修改,当然这要求设计厂商具备强大的研发实力和经验,因为现在的 IP core 相当复杂。 简而言之而言,硬核的性能更高、占用管芯面积更小,而软核则可以让不同厂商作进一步的修改。 ISA 的“实现”需要借助各种微架构,现在的处理器微架构基本上涉及以下部分: 流水线化 多核、多线程 SIMD 向量 存储系统分层结构 流水线早期一些采用非常简单的指令集(注意,我们说的不是 RISC)的电脑是采用单周期设计的,取指、解码、执行、写回都是放在同一个拍(周期)内顺序完成,此时的 CPI(每指令周期数)基本上是 1,但是这样设计的效率很低:当取指的时候,其余工位都只能瞎瞪眼等开饭,这样的设计也被称作非流水线化执行。
流水线化则是实现各个工位不间断执行各自的任务,例如同样的四工位设计,指令拾取无需等待下一工位完成就进行下一条指令的拾取,其余工位亦然。 世界上第一台采用流水线化指令执行的电脑为 1961 年的 IBM Stretch 或者说 IBM 7030,具备四级流水线工位,它同时也是 IBM 第一台晶体管化电脑。 这样原本四工位非流水线的一个周期是 800 个皮秒的话,在流水线设计的处理器上,虽然同样的指令完成时间依然是 800 皮秒,但是第二条指令则可能只需要在第一条指令完成时间加 200 皮秒即第 1000 皮秒就能完成,而非流水线设计则需要第 1600 皮秒才能完成。
RISC 指令集具备指令编码格式统一、等长的特点,在流水线设计设计上有得天独厚的优势,这样可以使得流水线工位设计相对于指令编码格式不统一、非等长的 CISC(例如 x86 的指令长度为 1 个字节到 17 个字节不等)来说显得更容易。 x86 可能需要将一些工位拆开(这意味着流水线工位更多或者流水线长度更深),例如英特尔的第一款流水线化处理器——486 的指令解码就是拆成两个工位。 流水线设计可以让指令完成时间更短(理论上受限于流水线执行时间最长的工位),因此将一些工位再拆开的话,虽然依然是每个周期完成一条指令,但是“周期”更短意味着指令吞吐时间进一步缩短,每秒能跑出来的指令数更多,这就是超级流水线的初衷。
例如 Cortex-A15、Sandy Bridge 都分别具备 15 级、14 级流水线,而 Intel NetBurst(Pentium 4)、AMD Bulldozer 都是 20 级流水线,它们的工位数都远超出基本的四(或者五)工位流水线设计。更长的流水线虽然能提高频率,但是代价是耗电更高而且可能会有各种性能惩罚。 既然流水线设计可以实现不间断取指、解码、执行、写回,那为何不干脆同时做几条流水线一起取指、解码、执行、写回呢?这就引出了超标量设计。 上图就是一个三路超标量四工位流水线的指令/周期执行示意图,可以看到 CPI 从 1 变成 0.33,即每周期执行 3.33 条指令,这样的改进幅度是令人着迷的,因此在初期的时候超标量甚至被人们赞美为标量程序的向量式处理。 不过在现实中不可能都这样,因为现在的处理器执行不同指令时候的“执行”段工位并不完全一样,例如整数可能短一些,浮点或者向量和 Load/Store 指令需要长一些,加上一些别的因素,实际大部分程序的实际 CPI 都是 1.x 甚至更高啊。 例如: a = b * c 这里的第二条指令需要使用到第一条指令的计算结果,因此必须等待第一条指令完成后才能跑第二条指令,更重要的是,在不少处理器上乘法指令并非一个周期而是需要多个周期才能完成。在遇到这样的情况时,就不能实现多指令发射而且会出现流水线停顿。 当然,还有更复杂的情况: if (a > 5) 将其按照汇编语言编写出来: cmp a, 5 ; a > 5 ?
ble L1
mov c, b ; b = c
br L2
L1: mov d, b ; b = d
L2: ...
这里的第二条指令是一个条件分支指令(ble 是小于或等于转移指令,ble L1 表示如果寄存器 a 小于等于 5 就转移到 L1 这行执行 mov d,b 这条指令)。 这条指令抵达“执行单元”的时候,位于流水线前段的取指单元和解码单元肯定已经拾取和解码了若干条指令,但是哪一条指令才应该接下来被执行呢?应该是第三、四条还是第五条呢? 在第二行的条件分支指令完成之前,处理器只能等待。处理器平均六条指令就会遇到一条分支指令,因此流水线设计带来的大部分性能提升优势此时会被丧失掉。 为此处理器必须进行“猜测”,按照猜测结果进行取指并推测哪些指令能开始执行,不过这些指令的执行结果并不会被递交(写回)直到分支指令的执行结果完成。 如果猜错的话,这部分指令的结果就会被扔掉,这也意味着这些指令对应的时间或者周期数会被浪费掉。当然如果猜中的话,处理器就能全速运行了。 那么如何去做“猜测”呢? 一个办法是所谓的静态分支预测,例如在指令编码格式里留出一个位元作为预测信息,编译器编译的时候,对这个位元进行标记,告诉处理器该跑那条分支,不过这对于已经采用了不具备这类条件执行指令的旧式 ISA 二进制程序来说这样显然是不可能的。 另一个办法就是“运行过程中”进行猜测即动态分支预测,通常是采用类似被称作“片上分支预测表”的单元来记录最近分支的地址以及用一个位元指示出哪一条分支是最近是否被采用的。 不过现在大多数处理器实际上是用两个位元来作标记的,因此单次的分支“不跳转”并不会马上导致一般的“跳转”预测出现反转(这对于循环边界来说是很重要的)。不过两位元分支预测并有考虑到分支相关性,所以人们后来有采用两级分支预测来解决这个问题,使得预测精度大大提高。 动态分支表需要占用相当可观的芯片面积,但是另一方面来说分支预测对流水线化处理器是相当重要的,所以是物有所值的。 不过就算是最好的分支预测技术也可能会猜错,对于超级流水线或者说深流水线来说就会有很多指令的结果会被扔掉,这样的情况被称作 mispredict penalty(误预测性能惩罚)。 像 Pentium III 这类具备非常先进分支预测技术的处理器,在遇到分支预测失败的时候,也会出现 10~15 个周期的性能损失,因此即使正确命中了 90% 的分支,也会因为分支误预测导致 30% 的性能损失,所以 Pentium III 其实很多时候会出现 30% 的时间在走冤枉路。 人们在 ISA 中引入条件执行指令(predicated instruction),希望籍此尽量减少分支,例如上面的例子,引入名为 cmovle 的判定指令后,可以写成这样: cmp a, 5 ; a > 5 ? mov c, b ; b = c cmovle d, b ; if le, then b = d cmovle 的作用是“当小于或者等于的时候就进行赋值”,只有在条件为“真”的时候才会递交执行,因此被称作条件执行指令。 采用了判定指令后,原来的 5 条指令变成 3 条,避免了两条分支指令,cmp 和 mov 可以并行执行实现 50% 的性能提升,消除了分支预测错误导致的大量误预测惩罚。 ARM 从一开始具备完整的判定指令集,而 MIPS 和 x86 后了也都添加了条件赋值指令,IA64(EPIC)中几乎每条指令都具备条件执行功能。 为了充分利用由于分支以及长时延指令导致的流水线“气泡(停摆)”而浪费的资源,人们引入了乱序执行(OoOE)技术。当出现需要等待某条指令的时候,程序中的指令会被“重排序(Re-Ordered)”,使得其他指令可以被执行。 对于像 x86 这样的 ISA 来说,32 位模式下的寄存器只有 8 个(ARMv7 是 16 个),如果程序里的变量较多,就会导致多个变量使用同一个寄存器的情况发生,这里有可能出现先读后写的伪相关现象。 微架构里解决寄存器先读后写(WAR)伪相关的办法就是寄存器重命名。在微架构的寄存器堆里塞进比 ISA 寄存器更多的物理寄存器,透过索引式寄存器堆或者保留站方式,将 ISA 寄存器映射到物理寄存器,从而实现乱序执行。 ARM Cortex-A8、Intel Pentium、Intel Atom(Bonnell 内核)、IBM Cell PPU 都属于顺序执行,它们选择顺序执行的原因主要是为了省电,因为 OoOE 需要大量的晶体管来实现。随着制程的改进,OoOE 的开销会逐渐淡化变得在某些场合里可行,因此像 ARM 从 Cortex-A9、Intel 从 Pentium Pro/Atom(Silvermont 内核)都开始采用 OoOE。 假设我们有这样的一段 C 代码: int x,y ; 由于 z 的初始化和赋值都是相对对立的,这里也许可以拆成两条 thread(线程): thread #1: int x,y ; 和 thread #2: int z ; 如果处理器的微架构具备两种架构状态让操作系统认为有两个处理器的话,上面的两条 thread 就能同时执行了,这就是多线程。 多线程有三种类型,即 SMT、FGMT 和 CGMT,其中最早实现 SMT 的处理器是 Intel 的 Pentium 4,而 FGMT 大都在 in-order(相对于 OoOE)处理器上采用例如 Cell PPU 和所有的 GPU 上。 随着半导体工艺提升以及功率墙壁垒横亘在前面导致超级流水线提升频率和各种指令并行度措施不再灵光后(这些限制其实在 20 多年前就被处理器厂商和科研界预见到,例如 1993 年 DEC 西部研究院 David W.Wall)的论文《LIMITS OF INSTRUCTION-LEVEL PARALLELISM》,1993 年英特尔在路线图中明确提出在 P8(当时还是 P5 或者说 Pentium)时代引入多核处理器)厂商开始在片上实现多个内核,这也就出现了多核处理器。 多核处理器能让支持多线程的程序、操作系统跑得更快,但是目前大部分的应用通常更偏好于单线程性能出色的处理器,因此你会看到单线程性能较强的双核处理器比单线程性能较弱的多核处理器更快的情况发生。 到目前为止我们介绍了指令并行、线程并行的微架构实现,不过除了这两种并行技术外,还有另一种非常常见的并行技术:数据级并行化,通常以 SIMD 向量方式实现。 SIMD 就是单指令多数据的缩写,理解起来并不困难,例如执行一条 SIMD 加法指令就能在一个周期里完成 64 条数据流发来的 64 个数字的加法运算。 SIMD 的初衷是为了摊薄大量执行单元上的控制单元成本,顺带减少程序的尺寸,因为SIMD 只需要复制一份代码就能开跑,而多核处理器(或者说 MIMD)需要每个内核都复制一份代码和在 cache 上共享多个程序拷贝。 SIMD 最好是用来跑结构相同的一堆数据,因此它是数据级并行的重要实现方式之一,而这类应用主要是多媒体为主,所以很多 ISA 都提供了专门的 SIMD 扩展来执行多媒体应用,ARM 有 NEON、Intel 有 MMX/SSE/AVX 等。 无论是冯·诺依曼还是哈佛结构的处理器,最理想的情况下当然是有无限大的存储空间和 0 时延的存储系统了,不过这显然是无法做到的,因此人们就提出了分层式的存储系统结构,从寄存器开始每往下一层容量就更大,但是速度也更慢: 例如对于 ARM Cortex-A9(四核 Tegra 3 的批发报价一般为 15~21 美元)来说: 物理寄存器堆大小是 56*32-bit = 224 字节 L1 cache 是 32-KiB(时延 4 周期) L2 Cache 是 1-MiB,不同大小区段的时延是:
不同型号的产品,搭配的内存容量不尽相同,以 华为 Ascend P1 XL 为例,搭配的内存大小为 1GiB,时延大概是 L2 + 110ns,带宽一般都有 1000MiB/s 以上。 基本上所有的手机都是采用 NAND 型闪存或者闪存卡作为 DASD(直接存取存储设备)来存放程序和数据,大小一般在 4 GiB 以上,如果搭配 Class 4 的 8 GiB microSD 卡的话读写带宽一般只有 1.x MiB/ss~3.x MiB/s(传输数据块大小为 4KiB 时)和 0.005 MiB/s~1.x MiB/s,价格一般为 20 元人民币左右 。 这里说的时延是从数据载入指令发出到数据抵达处理单元所需的时间,这通常并不难理解。 那么这里的 TLB 时延(TLB_L1/TLB_L2)又是怎么回事呢?这是因为虚拟内存的存在。 虚拟内存(virtual memory)的作用一般有两个:确保多个程序之间可以有效、安全地实现内存共享;让程序以为有大一块连续的内存空间(例如虚拟内存空间地址有 64-bit,但是我们的物理内存实际上只有 16GiB 或者说系统中的物理地址空间只有 34-bit,又或者是虚拟内存空间是 32-bit,而物理定址空间是 40-bit)。 对于用户程序在虚拟内存空间里操作的处理器,是需要把虚拟内存空间地址转换为物理内存空间地址,这就需要进行地址转换了。负责这个功能的单元一般被称作内存管理单元(MMU),有时候它又被称作分页内存管理单元,当然 MMU 的功能不仅仅是地址转换(否则就不会被盖这么大的名头了)。 内存的基本管理单位被称作 page(页面,或者说页块),不同处理器支持的页面大小不一样,一般都是 4KiB(在 ARMv7a 里还有 64 KiB、1MiB、16 MiB 等),性能导向型的处理器页面正变得越来越大,而嵌入式处理器似乎有 1KiB 大小的。 记录物理内存和虚拟内存关系里的数据列表被称作分页表,这些分页表也都是放在主内存(物理内存)中的,但是如果每次读写内存都要访问两次主内存的话效率太低了,所以人们引入了名为 TLB(Translate Look-aside Buffer,转换后缓存)的 cache 来改善这个问题。 不同的处理器 TLB 大小都不一样,以我们这里举例的 Cortex-A9 为例,本身就存在多种 TLB 配置形式,它的 L1 D-TLB 是 32 个条目(或者说分页地址映射),而 L1 I-TLB 可以配置为 32 或者 64 条目。 总之,早期的单周期式架构效率很差,因此人们引入了流水线设计,可以充分使用各级工位,各工位执行时间越短自然 CPU 的频率可以更快;然后人们又引入了超标量设计,让 CPU 上可以同时跑几条指令,随之而来的相依性等问题让架构师们想出了分支预测、乱序执行、寄存器重命名等等技术来保证处理器的指令执行效率。 除了提高指令并行度来改善处理器性能外,还有数据并行、线程化并行等方法,但是后两者都需要程序员和编译器协助,并非免费。 影响处理器性能还有内存的带宽和时延问题,因为取指和数据读写都必须透过内存访问来完成,层阶式设计是目前成本最为合理的方式。 在介绍一些稍微复杂的技术概念之后,我们不妨想看看 ARM 的由来。 ARM ISA 属于 RISC(精简指令集计算机,最关键特征是指令编码格式统一),ARM 本身就是 Advanced RISC Machines 的缩写,不过在早期它的全称是 Acorn RISC Machine(1983 年 10 月开始设计,1985 年实现第一枚硅片),因为公司当时的名字叫 Acorn。 Acorn 是一家 1978 年在英国剑桥成立的公司,这家公司生产过若干款在英国颇为流行的电脑,例如在当地教学市场占主导的 BBC Micro。 BBC Micro 取得了很大的成功,但是处理器是 8 位 的 6502,Acorn 希望切换到 16 位系统上来,但是英特尔拒绝了 Acorn 的 80286 样片申请。不过经过 Acorn 的多番实地考察和研究后,觉得在(当时)设计一个处理器的研发成本并不是很高,于是决定开始做 Acorn RISC Machine 这个项目。 基于 Acorn RISC Machine 的 ARM2aS 处理器获得了苹果公司名为 Mobius 的类 Apple 2 风格原型验证机接洽,这个项目后来因为苹果担心和大卖的麦金塔电脑产生冲突而腰斩,但是这次接触对 ARM 处理器的发展产生了一定的推动作用,因为 Mobios 团队对 ARM 寄存器做了一些小修改使得原型机的基准性能有不同幅度的显著改善。 后来苹果开始着手开发名为 Newton 的个人掌上电脑,他们发现似乎只有 Acorn RISC Machine 能满足要求耗电要求,但是当时 Acorn RISC Machine 处理器的内存管理单元并非 Acorn 自家,而是由 MEMC 公司提供芯片实现的,Acorn 没钱开发这个功能。于是双方就有了合作的想法,到了 1996 年 Acorn 和苹果合资组建了 ARM 公司,不过 Acorn 公司依然独立存在着直到 2000 年才基本烟消云散。 和一般的 RISC 不同的是,ARM ISA 除了指令长度固定为 32-bit(ARMv8 的 AArch 提供了 64-bit)的“经典 ARM” ISA 外,还有长度为 32-bit 或 16-bit 名为 Thumb(拇指)的 ISA 扩展。 Thumb 的目的是在低端或者说入门市场应用中改善 ARM 的指令密度(官方说法是减少大约 25%~35% 代码空间,按照 Linaro Dave Martin 的 Linux Kernel 编译结果,代码空间少了大概 20%),提高指令密度可以让 cache 塞进更多的指令减少命中缺失,更高密度的指令编码也有利于多线程因为可用寄存器资源更多了等。大部分的 Thumb 指令编码都能(经过位于指令解码器前的一个转译器实现简单转换)对应到经典 ARM 指令编码格式上。 Thumb 是 ARM 在嵌入式市场得以攻城拔寨的关键利器,在很长一段时间里都鲜有对手,Cortex 家族中用于单片机为主应用的 Cortex-M 甚至只支持 Thumb-2 指令(ARMv7 M),同样以授权方式运营的 MIPS 直到 2010 年才推出类似的 microMIPS 指令。 VFP(Vector Floating Point,向量浮点)是 ARM 架构的浮点单元协处理器扩展,提供了完全遵循 IEEE 754-1985 的低成本单精度和双精度浮点支持。虽然 VFP 打着向量的名头,不过这些“向量”指令的各个向量是串列方式执行(或者需要单精度搭配双精度才能实现并行执行)的,并不能提供真正的 SIMD 向量并行,因此这个向量模式被拿掉了。 Advanced SIMD(NEON)扩展在微架构实现中被称作 MPE(媒体处理引擎),是一个 64-bit 和 128-bit SIMD 指令集扩展,支持 8/16/32/64 位整数和 32-bit 单精度浮点数,共享使用 VFP 的寄存器。从 ARMv8 开始,NEON 在 AArch 64-bit 模式下提供完全遵循 IEEE 754 和双精度支持并且透过 VFPv4 具备 32 个 128-bit 寄存器。 Cortex-A9 的代号为 Falcon,是在 ARM 公司在 2007 年 10 月 3 日发布的 IP core,距今大约有五个年头。 Cortex-Ax 这个名字中后缀 A 表示属于 Application(应用处理器),Cortex 另有 M 系列(即单片机或者微控制器)、R 系列(实时应用),这里显然是 A 系列的规格最高,具备 MMU(内存管理单元)。 基于 Cortex-A9 的芯片实现有前面提到的 NVIDIA Tegra 2/Tegra3、Apple A5/A5X 以及 TI OMAP4430/4440、ST-爱立信 NovaThor U8500/U9500/LT9540、STM SPEAr1310、三星 Orion/Exynos 4210、华为 K3V2、ZiiLabs ZMS-20/ZMS-40、Sony CXD5315GG(PSV)、联发科 MT6577、华为海思 K3V2 等等,是目前 Google Android 操作系统高端手机、智能平板阵营中最主流的 CPU 内核。
Cortex-A9 的前身是 Cortex-A8,它们同属于 ARMv7 ISA 的实现,和 Cortex-A8 相比,Cortex-A9 除了流水线更短、增加了专门的多核方案等大家熟知的变化外,还具备多项改进。 1、Cortex-A9 拥有众多 RISC CPU 的先进特性,例如推测数据存取、动态分支预测、多指令发射、硬件 Cache 一致性、乱序执行、寄存器重命名,号称史上第一枚乱序执行移动处理器。 除了双指令发射和分支预测外,Cortex-A8 都并不具备,因此在 Cortex-A9 上汇编码优化、NEON SIMD 的重要性相对来说要低很多(经过调优的汇编码在 A8 上可以做到 10-30 倍性能,而 A9 一般只会有 2-5 倍,如果是 A9 使用 NEON C Intrinsics 的话性能基本上和汇编一样)。 2、Cortex-A9 的每条 L1 Cache Line 是 32 字节,Corte-A8 是 64 字节。Cache Line 又称作 data block(数据块)或者 Cache Block,Cache 每次更新都以固定大小的 Cache Line 为单位。 Cache Line 的大小主要影响命中率、内存存取效率、发生 Cache 命中缺失时候的性能惩罚时间。 3、Cortex-A9 的 L2 Cache 位于“核外”( ARM 对应的方案是 PL310 或者更新一点的 L2C-310),而 Cortex-A8 则是速度更快的核内 L2 Cache。 从对 Cortex-A8 1GHz(三星 Samsung Hummingbird,即 Exynos 3110)和 CortexA-A9 1.2GHz(三星 Exynos 4210)实测来看,A8/A9 的 L1 cache 延迟分别为 3 周期和 4 周期,L2 Cache 延迟(含 L1 Cache 延迟但是不含 L1/L2 TLB 命中缺失惩罚的情况下)分别为 13 周期和 23 周期。 4、Cortex-A9MPCore 的各内核 L1 Cache 采用了数据、代码分离式设计,L1 数据 Cache 具备硬件 Cache 一致性。各个内核共享外部 L2 Cache。 5、Cortex-A9 具备完整的 VFPv3 FPU,而 Cortex-A8 则只有缩水版的 VFPlite,主要区别是 Cortex-A9 的大多数浮点操作都只需要 1 个周期,而 Cortex-A8 需要 10 个周期,因此 Cortex-A8 的浮点性能相当烂。 6、Cortex-A9 支持半精度(fp16),而 Cortex-A8 只支持 32-bit 单精度(FP32)和双精度(FP64),不过半精度在 CPU 级别的应用并不是很多见。 7、Cortex-A9 不能同时发射两条 NEON 指令,而 Cortex-A8 却能够实现 1 条 NEON L/S 指令搭配一条非 L/S NEON 指令。 8、Cortex-A8 的 NEON 单元位于 ARM 单元下游,所以 NEON 单元访问寄存器和内存更快,而且数据可以很快从 ARM 寄存器搬到 NEON/VFP 单元寄存器,但是将 NEON/VFP 寄存器数据搬到 ARM 寄存器的话就非常慢,会导致 Cortex-A8 的流水线停摆 20 个周期。 9、Cortex-A8 的 NEON 和 ARM 各有一个分离的 L/S 单元,如果一起对同一块 Cache Line 进行 Load 或者 Store 操作的话,会导致额外的 20 个周期延迟。 10、Cortex-A9 对多线程化同步采用 LDREX/STREX,不会杜塞所有的内核,而 Cortex-A8 对互斥使用简单的断禁制。 11、所有的 Cortex-A8 都集成了 NEON SIMD 单元,但是 Cortex-A9 则未必,例如 NVIDIA Tegra 2 就没有集成 NEON,不过 Tegra 3 则具备 NEON。 如果使用 7-zip(不包含任何浮点)实测来看,Cortex-A8 1GHz 的压缩(受内存时延、数据 Cache 大小和速度以及 TLB 影响较大)/解压缩(受 CPU 整数性能影响较大)性能相当于 Core i7 920 2.67GHz 的 3.5% 和 5.5%;而 Cortex-A9 双核则是 Core i7 920 的 8.8% 和 12.7%。 代号 Eagle 的 Cortex-A15 是在 2012 年 9 月发布的 ARMv7 架构实现,是 ARM 首次引入三路指令解码的微架构 IP core,目前三星的 Exynos 5 5250(双核,32nm HKMG,1.7GHz)是市场上能看到的第一波 Cortex-A15 产品,Chromebook、Nexus 10(均在 2012 年 10 月发布)都采用了这枚芯片。 和 Cortex-A9 相比,Cortex-A15 有非常明显的变化: 1、整数流水线最短工位数达到 15 级,管芯面积占用比 Cortex-A9 高一倍。 2、采用三路超标量微架构,可以每个周期取指四条指令,解码器每个周期可以为发送单元提供 3 条指令,而指令发射单元可以乱序提供最高 8 个微操作供执行单元运行。 相比之下,A9 的解码器只能每周期跑两条指令,派发单元每周期派发 4 个微操作给执行单元。 3、Cortex-A15 的动态分支预测技术和 Cortex-A8/A9 差不多,但是 A15 引入了一个 64 条目的 microBTB,而此前的 A8/A9 并不具备这样的分层结构。动态分支预测能力是影响现代风格处理器的关键因素之一,像 Pentium 4 的 BTB 是 4K 条目,SandyBridge 据说达到 8K~16K。 虽然 A15 的两级 BTB 条目总数较 A8/A9 少,但是 A15 的 Return Stack 条目数从 8 条增加到了 18 条,取指带宽从之前的 64-bit 提升到 128-bit,而且完全支持边界非对齐地址的拾取。 4、Cortex-A15 支持 VFPv4,具备硬件 FMA 指令执行,可以在同频下提供两倍的峰值浮点性能。此外,A15 还具备硬件除法指令,在 A9 上这需要接近 50 个周期来执行。 5、A15 的周边总线为 AMBA4,128-bit master 界面,A9 的 AMBA3 的 master 界面是 64-bit。 6、虽然 ARMv7 是 32-bit ISA,但是现在 Cortex-A15 支持 40-bit 物理定址(类似于当年的 Pentium Pro 和 Atlhon),而且 L1/L2 Cache 具备 ECC,因此理论上适用于服务器级应用。 7、A15 和 A9 都有一个类似的 small loop 缓存,用于存放小循环,让执行单元无需访问指令 cache 就能抓到指令。在 A9 上它可以存放大小为 64 字节的指令。 而在 A15 上则是 32 条目,可以存放两条前转分支和一条后转分支,而且 A15 的 small loop 缓存存放的是已经解码的微操作,这意味着连解码步骤也能节省掉。 这类似于 Intel 的做法:先在 Conroe 上引入 loop buffer,然后在 Nehalem 引入 uop loop buffer(28 条目),到了 SandyBridge 则彻底改成了 uop cache(1500 个 uop),逐步改进。 Cortex A15 的整数性能为 3.5~4.01 DMIPS/MHz,相比起 A9 的 2.5 DMIPS/MHz 和 A8 的 2.0 DMIPS/MHz 有明显的改进,不过因为三路超标量而带来的各种资源增加,A15 需要更先进的制程(32 纳米或更先进)才能在手机、平板上变得比较适用。
虽然 2012 年年初的时候 NVIDIA Tegra 3 大放异彩,但是到了临近年末的时候,高通的 Snapdragon 4 Pro APQ8064 却已经是成为了几乎所有性能导向新 Android 手机的主角,其中一个重要原因就是它采用的 Krait 微架构能提供对手不具备的特性。 Krait 微架构是高通第四代 Snapdragon(骁龙)处理器所搭配的 CPU 内核微架构,是 ARMv7 架构的实现,属于高通的 ARM 架构级授权、自行研发的处理器内核微架构。 Krait 的前身是 Scorpion,在产品布局上它和 Scorpion 有些类似,例如 Scorpion 定位于 Cortex-A8 和 Cortex-A9,而 Krait 的定位也是类似,即 Cortex-A9 和 Cortex-A15 之间,具备一些 Cortex-A15 的特征。 例如 L0 cache(Cortex-A15 上有类似作用的 loop buffer,相当于 L0 I-cache,指令调度器无需经过解码器就能抓到小循环的微操作指令)、三路超标量、VFP4 浮点单元、128-bit SIMD 处理能力(高通称 SIMD 单元为 VeNum,ARM 自己则称之为 NEON)以及基于 A15 同级的半导体制程节点。至于有人说 Krait 是 A9 的改进版,这样的观点我很难认同,它和 Scorpion 都类似于当年 DEC 获得 ARMv4 ISA 授权而自行研发的微架构。 不过另一方面,Krait 的乱序执行要逊色于 Cortex-A15,后者具备八个指令发射端口和八个执行端口,每一个执行端口都对应一个(准)保留站(有些类似于 AMD K7-K10),而 Krait 只有四个指令发射端口和七个执行端口,并且采用的是类似 Cortex-A9 或者说 Pentitum Pro 方式的单个大规模指令发射队列单元。
在现实测试中,Krait 的表现和它的微架构一样,提供了比 Cortex-A9 更强的性能,在对单线程性能较高的应用中,即使是双核版的 Karit 都可以比四核 Cortex-A9 更快。 正如我们前面提过的,苹果公司在上世纪九零年代就已经和 ARM 合作并且提供了一些微架构设计上的修改方案,因此苹果对 ARM 一点都不陌生甚至有非常丰富的经验。 从 iPad、iPhone 4/iTouch 4、Apple TV 2 开始,苹果开始真正介入 ARM 芯片设计,推出了名为 A4 的自行设计 ARM 处理器。A4 采用了 ARM 授权的 Cortex-A8 IP Core,但是苹果找来了 Intrinsity 公司(已经被苹果收购)和三星公司合作进行了一些调优,可以让 A4 的频率跑得比基于上一代制程的 Cortex-A8 更快。曾经有说法认为 A4 的 L2 cache 大小是 640KiB,但是后来确认修正为 512KiB(这是 ARM Cortex-A8 内核的可选配置方式之一)。 A5 系列依然是采用 ARM IP core,从 Cortex-A8 升级为 Cortex-A9 双核,不过整个 A5 系列出现了三个版本,即 APL0498、APL2498、APL5498(A5X),三个版本的芯片面积各不一样,其中 A5X 的 GPU 是四核 PowerVR 5 并且拥有 4 通道内存总线,定制化设计在这里体现得非常明显。 真正的定制化设计是从 A6 开始,苹果公司给 A6 搭配的 CPU 内核是完全有自己团队开发的 Swift,不仅这样,苹果还提出了一个新的名字:ARMv7s。传统上,ARMv7 是属于 ISA 版本名称,不过 ARMv7s 至今都并未出现在 ARM 官网的公开资料里,因此 ARMv7s 可能并非 ARM 的产物,而是苹果自己在 ARMv7 基础上做的一个架构优化定义,让编译器可以为 Swift 微架构匹配对应的调优,本质上 ISA 还是 ARMv7A。
那么 Swift 和以往的 Cortex-A9 相比有哪些改进呢?苹果公司并未详细说明,传统上这家公司就是这样,千方百计捂着,不过 Anandtech 利用一些自己编写的微型基准测试程序进行了一些探测,以程序员的角度大致估量出了 Swift 的微架构是长得如何了。 在前端部分,Swift 具备三个指令解码器,可以每个周期完成三条指令的解码,而在指令分发器上,具备五个发射端口,浮点单元、整数单元各占两个,还有一个专供 Load/Store 单元使用,具备乱序执行能力、整数流水线深度为 12 级,cache 子系统的时延比 Cortex-A9 低了差不多一半。 “ARMv7s”的设立估计就是让编译器获知编译执行对象是 Swift,这样就能对各种指令顺序进行一些预调度,确保尽可能低的 CPI。 简而言之,A6 系列就是采用了比 A5 系列更先进制程和微架构的产物,其中的 CPU 内核则是苹果首次真正完全执行开发的设计,未来是否会在 GPU 上也有类似的动静将会是值得关注的。 Atom 是英特尔计划实现 x86 anywhere 战略的重要产品,为此它不惜卖掉了口碑不错的 Xscale 系列 ARM 处理器部门给 Marvel,从 2008 年 3 月发布迄今已经有了 45nm 和 32nm 两代制程,产品型号可以说是多如牛毛,就代号而言,有最初的 Silverthrone、Diamondville,然后经过制程改进,分别有了 Lincroft 和 Pineview,“新近”的 Cedarview 则是源自 Pineview。 不过这么多型号,到目前为止它们所基于的内核微架构都是 Bonnell。第一代的 Atom 处理器(Silverthrone)是 45 纳米高性能制程制造,但是需要另外搭配一个 TDP 两瓦的 130nm 制程芯片组,这枚 Atom 虽然有低于 1 瓦的版本,但是此时很多功能都被关闭,性能很弱,考虑到那个芯片组,根本不会有人拿这个做手机产品。 两年后的 Lincroft 集成了 GPU、视频单元以及内存控制器,采用专门的 45 纳米 SoC 工艺制成,但是依然需要搭配一个代号 Langwell、由台积电 65nm 制程生产的 I/O 芯片,两者合起来的名字叫 Morrestown 平台,这个系列中的 Z600 被尝试用来做了一两款手机,但是太高耗电的问题使得它们依然难以成为智能手机市场的竞争者。 到了 2012 年,名为 Medfield 的新平台似乎让英特尔的支持者看到了些许的曙光,因为在经过三次制程技术和三个不同的设计后,现在英特尔终于有了一个可以在耗电上达到智能手机要求的低功耗产品,这个平台中基于 32 纳米 SoC 制程的 Penwell 芯片集成了代号 Saltwell 的内核,在微架构上,Saltwell 和之前所有 Atom 处理器的内核微架构其实都是几乎一样的,都属于 Bonnell 微架构,不过 Saltwell 由于采用了更精密的 32nm 制程,得以在微架构上做一些优化,因此在细节上是有一些不同的。
Bonnell 采用超标量流水线设计,可以每个周期执行最多两条指令,指令需要遵循一定配对原则才能实现超标量执行(类似于 Pentium 的 U/V 设计),具备 16 级工位,支持 x86_64 指令集以及最高 SSE3 扩展,但是手机版本只支持 32-bit ISA,内存容量也被限制在 1GiB,对应平板和低端笔记本等版本则打开了 64-bit ISA 支持,内存容量放宽到 2~4GiB。 相对于当前的许多竞争对手来说,英特尔在产品技术细节公布上要大气许多,各种数据表、涉及微架构内部关键特征的编程优化手册都能在产品发布后就能公开下载到,这让我们可以更详细的为大家介绍这款产品。 1、Saltwell 的分支预测器是一个具备 8096 条目(两倍于 Bonnell 4096 条目)的全局式分支预测器; 2、Lincroft 时代引入的 48 字节后段取指缓存(post-fetch instruction buffer)在 Saltwell 里升格为一个高速缓存(Cache),以便减少 Saltwell 的重复取指。该技术类似于 Conroe/Merom 的 Loop Stream Detector(循环指令流侦测器),前面我们在介绍 ARM Cortex 微架构的时候也有提到类似的技术。 3、Saltwell 的 L1 I-Cache 是 32KiB 8 路相关联,L1 D-Cache 是单端口 24KiB 6 路相关联。 4、Saltwell 的指令发射端口依然和 Bonnell 那样是采用 Pentium 配对式发射风格的 U/V 流水线设计; 5、Saltwell 能实现更多的整数指令配对以及更快的 memcopy 微代码规则。 6、加入了不间断时间标签计数器(TSC)和本地 APIC 计时器,主要是为了协助电力管理和减少唤起 CPU 的情况。 7、L2 Cache 维持之前的 512-KiB 8 路相关联设计,运行于内核同频,读取带宽为每周期 32 字节(256-bit),可支持 32 个待发 cache 请求。改变的地方主要是 L2 Cache 的电压轨线与内核是分开了的。例如 Saltwell 内核的 Vmin 是 0.7 伏特,L2 Cache 则在固定的 1.05 伏特电压轨线上跑,这样的设计有助于减少 C6(最节电模式)电力状态转换时延。 8、频率变频粒度更精细。以 Z2460 为例,虽然 CPU 的最高持续频率为 1.3GHz,但是频率的变动范围达到 1.6GHz,步进粒度为 100MHz;而之前的 Z600 系列频率范围是 0.2GHz ~ 0.8GHz 持续,最高 1.2 GHz。 9、Saltwell 和之前的 Bonnell 系列微架构同样没有专用的硬件整数乘法、除法单元,这些操作都是和浮点硬件共享。 10、在 Medfield 中还有一块独立分离于 512 KiB L2 Cache 外的 256KiB SRAM,位于不间断模块内,主要用图像信号处理器存放图像数据以及优化最低漏电。在 SOC 进入节电模式后,这块 SRAM 还会被用于存放架构状态,就好象 Saltwell 内核具备自己的 C6 SRAM 来存放 x86 状态,这块更大的 SRAM 则是存放整个平台的。在进入 S0ix 状态时,像图形或者视频编解码器等单元都会被关掉,它们的状态信息和配置信息都会保留在这块 256 KiB SRAM 里。 中低价位的智能手机势必成为 2013 年亮点,海量的千元以下甚至 600 元以下的智能手机、平板电脑将会在这一年推出,不过因为成本限制,它们在各方面的规格必然比更高价位的产品有所削弱,其中之一当然是必定搭载的应用处理器。 中低价位市场是 ARM 所最擅长的领域,目前它的产品线中除了像当年 Apple iPhone 1 所使用的 ARM11 内核外,还有接替 ARM11 的 Cortex-A5 以及接替 Cortex-A8 的 Cortex-A7。
1、Cortex-A5 是目前 Cortex-A 系列中最低阶的内核,和 ARM11 的 1.2 DMIPS/MHz 性能相比,Cortex-A5 达到了 1.57DMIPS/MHz; 2、Cortex-A5 具备 ARM 最新的 VFPv4 浮点单元和 128-bit NEON 向量处理单元。,相比之下 ARM11 只有老式的 VFP11; 3、Cortex-A5 的制程为 40nm,面积是 90nm 制程 ARM11 的一半。 4、Cortex-A5 可以提供单核、双核、四核等配置,像联发科就做了一个价格非常低的 Cortex-A5 四核方案,在低价位手机市场里竞争力非常强大。 5、Cortex-A7 的 DMIPS 性能是 1.9 DMIPS/MHz,Cortex-A8 是 2.0 DMIPS/MHz。 6、Cortex-A7 具备硬件整数除法、虚拟指令、40-bit 内存定址能力,所有 Cortex-A15 的程序都能在 Cortex-A7 上执行。 7、Cortex-A7 和 Cortex-A8 类似集成了一个低时延(10 周期)的 L2 Cache。 8、Cortex-A7 的整数流水线是 8 级顺序双发射,分支预测单元比 Cortex-A8 更先进,因此在分支预测能力和分支预测失败惩罚方面都会比 Cortex-A8 更好; 9、虽然不能像 Cortex-A8 那样双发射浮点或者 NEON 指令,但是 Cortex-A7 的浮点单元是流水线化设计。 10、在同样的制造工艺节点下,Cortex-A7 的面积是 Cortex-A8 的 1/3~1/2。 11、Cortex-A7 能实现单核、双核、四核等配置,而 Cortex-A8 只有单核配置。 12、Cortex-A7 在 ARM 的 big.LITTLE 策略中属于伴核角色,就是给 Cortex-A15 作为低负荷工作的杂役。 从定位上看,我们相信 Cortex-A5 在低价智能手机市场上会有相当夺目的表现,而 Cortex-A7 作为非伴核的单独产品时则更多的会在中低价平板电脑市场上攻城拔寨。 目前移动图形 GPU 大致上有五个阵营,即 ImgTec PowerVR、ARM Mali、高通的 Adreno、NVIDIA GeForce ULP 以及 Vivante(中文名是:图芯),由于 Intel 下一代 Atom 中将会应用自己的 GPU,因此很快就会扩展成为六个阵营。这里的 Vivante 的人是来自 NVIDIA 的,如果你仔细看 Vivante 的文档就会发现 Vivante 的很多“市场行销式术语”都和 NVIDIA 极其相似。 在这几家厂商中,做移动图形时间最长的当然是 ImgTec PowerVR 了。 不仅与此,PowerVR 对于许多九十年代中就已经接触 PC 的游戏玩家来说也不陌生,当年的图形加速卡概念刚刚被炒作起来,做图形加速器(注意,不是板卡哟)的厂商多如牛毛。例如 ATi、Tseng Labs(代表作是 ET4000)、Rendtion(代表作是 V閞it?2x00)、3dfx(代表作是 Voodoo 2 三维加速芯片)、PowerVR、Bitboys、GigaPixel、Trident、S3 Graphics、3D Labs、Cirrus Logic、Alliance Semiconductor(代表作是大名鼎鼎的 ProMotion 6410,VCD 最流行的时候,6410 就是显卡代名词)、Matrox、Chromatic Research(代表作是 Mpact! 系列可编程多媒体芯片)、Number Nine(代表作是 Imagine 128,传说中的神作,当时 2D 显卡的巅峰一个是 Matrox,另一个就是 Number Nine),NVIDIA 在当时同样也只是一家刚刚起步的公司。 这里有一张历史树图:http://www./images/stories/doc/historysm.png PowerVR 在这众多的图形芯片公司中是一家很特别的厂商。首先它是以技术授权方式将设计转让给其他芯片公司,由其他芯片公司将设计物理化后成为真正卖给厂商的芯片,其次是 PowerVR 的渲染架构是分块式延后渲染,理论上可以完全消除像素的无效重复渲染。 在当时,极少有图形芯片公司是这样的方式运作以及具备这样的渲染技术,当然并不是说完全没有,除了 PowerVR 外,还有一家名为 GigaPixel 的公司也是采用授权制和具备分块式延后渲染(被称作 Giga3D 架构,具备比当时 PowerVR 兼容性更高的分块式延后渲染设计以及采用 eDRAM 的特点)的,不过这家公司出彩的时间没有几天就被 3dfx 收购,而 3dfx 的所有资产后来也被 NVIDIA 收购了,其中也包括 Giga3D。 PowerVR 的渲染模式是 tile-based deferred rendering(分块式延后渲染)。 分块式渲染(TBR)并不难理解,就是把画面切成若干个 16x32 或者 16x16 的像素块进行渲染,这样的好处是可以在芯片上建立一个中间缓存(也可以称作 Tiler Buffer,分块缓存,里面用于存放当前渲染 Tiler(像素块)的深度/蜡版帧缓存、色彩帧缓存、渲染对象等),不再需要片外的显存来存放 Z-buffer,让渲染过程中的读写尽量在片上完成,减少内存的读写。 由于在中间缓存渲染的时候都是很高的精度(IEEE 32-bit),减少了以 16-bit(例如 R:G:B=5-bit:6-bit:5-bit)帧缓存模式时在内存上进行透明混合等操作时的精度损失,因此 TBR 可以较低的内存读写和占用实现高品质的输出。 ARM 的 Mali、当年 Bitboys 的 Glaze3D 都属于 TBR,不过也仅此如此,它们并非 TBDR,仍然属于 IMR(立即渲染器),只有有限的 HSR 能力(例如 Early-Z、Hi-Z 之类的技术),并不能完全消除无效渲染。 TBDR 是在上面的分块式渲染(TBR)基础上增加了对场景中当前屏幕画面三角形的筛选分仓(binning)的步骤,将三角形的前后位置关系标记起来并存放于片外的显存中,这样就能实现将不可见面在进入着色渲染流水线之前剔除掉,实现完全消除无效渲染。 由于增加了分仓动作,贴图和着色必须等待三角形可视性问题解决后才渲染,渲染上增加了时延,所以这种渲染方式被称作分块式延后渲染。 不过在 OpenGL 中缺乏专门的标记来指示一帧画面什么时候开始和结束,所以 TBDR 对一帧画面什么时候才接收到所有的三角形进行侦测将会有点麻烦,这会导致三角形分仓陷入迷失中。 在 Direct3D 中有 BeginScene() 和 EndScene() 这样的标记,但是由于在几乎所有的硬件上都没有效果,所以开发人员都会懒得去用这些标记并且随意地在这些界限外使用 z-buffer,这会导致 API 无法确保 z-buffer 中存放有效的数据。PowerVR 硬件本体虽然可以把 Z-buffer 存放在片外显存中,但是代码必须编写正确。 TBDR 可以减少无效渲染、实现极高的低内存占用渲染输出品质,但是它的缺点是需要做一块容量不小的片上缓存和大量的晶体管确保 TBDR 时候的兼容性,因此 PowerVR 的芯片面积一般都比 GeForce 这类 IMR(立即模式渲染器)大不少,另一个麻烦之处在于行销的时候,PowerVR 的纸面规格相当难看(当年 PowerVR3 就是搭配 SDR 作为显存上市的,而此时市场上的许多显卡都已经搭配 DDR 显存了),当然这个可以透过一些媒体测试实证加以解决。 上图是 PowerVR SGX54X MP4 的微架构图,这个系列中的 PowerVR SGX 543 MP4 曾经应用于苹果 iPad 3 中的 A5X 应用处理器中,MP4 表示它是以四内核形式组成的 GPU。 需要注意的是,PowerVR 说的内核是真正的内核而非 NVIDIA/AMD 那样的把单个 ALU 都当成 core 的市场行销术语,它这里的四个内核可以并行处理四个三角形渲染,NVIDIA 到了 Fermi(GTX 480)开始实现多三角形渲染,而 AMD 是在 Tahiti(7970)开始实现。 在 PowerVR 54x MP4 中,每个图芯渲染计算单元被称作 Multi-Threaded Co-Processor,对应 OpenCL 的术语就是 PE(Processing Element,处理部件)。每个 PE 每个周期可以完成两个浮点操作。 每四个 PE 构成一个 Pipe(渲染流水线,因此 Pipe 本质上就是一个四路 SIMD),每个 PowerVR SGX54X 内核包括四个这样的 Pipe,即 16 个 PE,故此 PowerVR SGX54X MP4 就有 64 个 PE。 因此如果 PowerVR SGX 54x MP4 运行于 300MHz 的话,浮点性能就是 38.4 GFLOPS。 即使是同一代的 PowerVR,不同的内核版本具体的实现细节都可能有些差别,例如 Pipe 内的 PE 数或者是每个内核内的 Pipe 数,例如 PowerVR SGX 554 MP4(Apple A6X 采用该 GPU)的每个内核有 8 条 Pipe 而非 PowerVR SGX 54x MP4 的四条。 PowerVR SGX 5 被设计成统一渲染结构,即几何体顶点和屏幕像素计算都是由上面说的 PE 执行,这样的好处是让 GPU 内的计算单元可以尽量保持运作状态,而不是像分离式架构那样遇到非平衡负载的处理时候,VS(顶点计算单元)有时候在等 PS(像素着色计算单元)或者 PS 在等 VS。 根据 PowerVR 的资料,SGX 54X 的每个 Pipe 内有一个线程调度器(Thread Scheduler),每个线程调度器内有 16 个线程可供派发,每次可以派发其中的 4 个线程给下面的 PE 执行。 PowerVR SGX 5 系列中有明确的 API 支持规格的内核基本上都是支持 DX9.X,但是有一个特例,那就是 PowerVR SGX 545,可以实现 DX 10.1、OpenGL 3.2 支持。 如果资料没有错误的话,PowerVR SGX 5 的 ALU:TEX 比例为 2:1,即每两个 PE 就会配上一个纹理单元,因此我们这里的 PowerVR SGX 54x 单个内核具备 8 个纹理单元。 虽然说 PowerVR 微架构的资料并不是很多,但是相对于除了 Intel 的其他对手而言,已经是非常大方了。 在本文中,我们首先指出了当前手机、平板电脑所使用的应用处理器与平时大家接触的电脑仍然存在巨大的性能差别,以性能来看的话,可能是 6~10 年的距离。 由于电池和散热的限制,移动应用处理器不可能像台式处理器那样相对较少地考虑耗电问题,对移动应用处理器来说,所有的一切都得围绕一个词进行:省电。 省电不只光靠制程上的改进,还有芯片本身的设计也是极为重要的,例如英特尔的 Atom 在实验室的时候采用了 6T(单位元六个晶体管)的 Cache 设计,速度和面积都不错,但是为了省电,后来上市的产品转用了 8T(单位元八个晶体管),这样的设计会增加不少面积,但是更省电了,类似这样牺牲芯片面积换取功率控制的措施在移动应用处理器上比比皆是。 不过差距并非完全来自于处理器本身,像 Android 这个操作系统,程序是跑在一个 Google 自己做的虚拟机上面,绝大部分 apk 的开发语言都是 Java,这使得问题变得更加严重。 在这个博客里,博主采用 C 和 Java 两个版本的程序在 Android 上作对比,得出的差别是 C 版本跑了 8 秒,而 Java 是 57 秒。类似这样的区别在 C 和 Java 的对比上其实比比皆是甚至往往会出现更加巨大的差别。 所以这边架构师和半导体工厂绞尽脑汁做了一个性能/耗电比非常出色的产品,但是如果碰上使用 Java 来编写性能敏感型应用的时候往往会被 Android 毫不留情地从工业时代打回石器时代,而台式机这边已经是太空时代,差距就这么明显。 这就是一个整天吹嘘所谓“手机看大片”的移动时代的悲哀,但愿可以快点结束。 写了这么多东西,肯定有人不耐烦了:你说这么多屁话有啥用,直接告诉老子什么处理器最好不就得了。 就等你这句话,因为这个问题一点都不难回答。 从上面大家可以得知,软件对性能的影响,所以从现实出发,我推荐大家都选择 iOS 下的产品,因为这个操作系统对应的开发平台基本上都是使用本机语言代码编译程序的。 这是一个技术正确的回答,但是“政治”上未必正确,因为 Android 的厂商实在太多了,相关的用户群也是海量级,随便一口口水就能把我给淹没掉,所以还是需要给这个用户群体推荐的。 如果以已经发布的产品,我倾向于像 N 记 Tegra 4 这个产品,它有一些比较特别之处。首先,它是集成了 Cortex-A15 四核处理器,这是高通 Krait 架构不可能相提并论的微架构,其次是它的 GPU 部分,虽然不太可能比得上 iPad 4 中 A6X 采用的 PowerVR SGX 554MP4,但是性能和其他同级产品的最快图形内核相比应该也是叮当马头,要知道 Tegra4 的芯片面积只有 80mm^2 级别,而 A6X 已经达到 123mm^2。还有就是 N 记似乎和游戏业界比较熟络,对于希望手机玩玩游戏的人来说更有保障。 什么?对游戏不感兴趣,那就挑个联发科的四核 Cortex-A5 手机好了,最省功夫。 由于 Ti、ST-爱立信的退出,现在移动应用处理器的厂商虽然看似热闹,但是已经露出了一些红海的迹象,或者说骨头变硬了、肉变少了,将来剩下的厂商必定是具备较强大技术储备和充足资金支持的。 英特尔是最具这样特征的公司,他们的下一代 Atom 脚步正越来越近,乱序执行的引入和比所有对手提前一年导入的 22 纳米制程势必引来业界对英特尔在移动应用处理器上前所未有的重视,至少对我来说就很有点当年 Pentium 升级 Pentium Pro 的期待。■
|
|