决战不仅在2010:新Intel显卡架构初览
● Larrabee 是什么东东? 从具体的名称而言,Larrabee 可算是一个在三年前就已经冒出来的名字,首次被证实的文件是一份 Intel “不小心”散布到网络上的幻灯片——"Tera Tera Tera"。在这份幻灯片中,我们首次看到
● Larrabee 是什么东东?
从具体的名称而言,Larrabee 可算是一个在三年前就已经冒出来的名字,首次被证实的文件是一份 Intel “不小心”散布到网络上的幻灯片——"Tera Tera Tera"。在这份幻灯片中,我们首次看到了 Larrabee 的设计方向、大致架构,特别是其中提到的基于 x86 ISA 部分在当时更是引起了大家的轰动。
Larrabee 本质上的确是一枚基于 x86 的处理器,不过它的片上内核规模达到了前所未有的数目:32 个甚至更多,不过另一方面它又属于所谓的同 ISA 异质架构概念,这就给 Intel 带来了一系列的挑战,特别是如何确保较高的执行并行度、如何面对其首番出场所要面对的最大挑战——游戏图形渲染与通用计算的平衡。
和 NVIDIA、AMD 以及其他传统 GPU 厂商未到最后一刻绝不对外公布新 GPU 体系架构甚至根本不曾透露(例如 NV30)的做法不同的是,Intel 对 Larrabee 的体系架构除了一些执行细节外基本上是和盘托出,而这还是距它正式发布的应该有差不多两年多的时间点。
当然,不仅 Larrabee 如此,事实上 Intel 历史上发布的各种处理器大都能提供非常详细的数据表、手册、开发指南以及配套的开发工具,在技术资源方面力度上是毋庸置疑的。
如此大方的安排有助于我们大致了解 Larrabee 的架构,特别是对许多喜欢一睹为快的读者来说更是难得的机会可以了解未来 GPU 或者 many-core 处理器的发展方向。
不过在介绍 Larrabee 之前,我觉得有必要先说说其推出的背景,这对于了解 Intel 为什么要推出 Larrabee 以及如何实现 Larrabee 是至关重要的。
#p#副标题#e#
● 为何要推出 Larrabee ?
正如大家所知道的,从 DirectX 10 开始,Vertex Shader 和 Pixel Shader 的 ISA(指令集架构)已经是统一,VS 和 PS 都能在同一个单元上完成,加上 Stream Out 的引入以及各类开发工具的推出,把 GPU 应用于通用计算领域已经是渐入佳境的话题。
与以往学术机构里作学术研究的各种 stream processor 不同的是,GPU 有非常庞大、可以媲美桌面 CPU 的市场规模,这使得开发人员能够很容易就获得便宜的产品为大量的潜在用户做相应的 GPU 通用运算开发,为软件增加卖点并获取更高的附加值,没有多少人在怀疑这个市场已经在蠢蠢欲动。
让我们在看桌面 CPU 这面的情况,和整个 90 年代以增加门电路数量密度、时钟频率以及指令级并行相比,到了 2003 年整个业界都认识到了电力、发热的物理屏障已经让时钟频率的增长难以维继,而在指令级并行方面,实现复杂的分支预测、推测执行所占用的芯片成本与所能达到的性能提升相比也都开始变得不怎么划算了,摆在人们面前的性能提升道路似乎就剩下增加门电路这条路还是可以继续冲的。
在未来的 10 年里,我们相信半导体产业依然维持着每两年晶体管数量增加一倍的发展趋势,在这样的背景下,人们自然而然地想到了推出多核产品,这不仅仅是指目前大家看到的双核、四核,随着半导体工艺的推进,更多内核的 CPU 也将在未来的日子里问世,半导体厂商从来都不会让自己庞大的产能闲置着。
Intel 新近推出的桌面处理器为 Nehalem 架构,这个架构是一枚 4 cores 的 45nm 桌面处理器,芯片面积大约是 246mm^2,支持SSE 4.2,在 3.2GHz 频率下的峰值浮点性能为 51.2 GFLOPS(双精度)或者 102.4 GFLOPS(单精度)。
这个数据的确要比目前的 Yorkfield 高一倍左右,但是与 GPU 相比的话就不怎么样了。
基于 55nm(其实是 65nm half-node)的 AMD RADEON HD 4870 芯片面积为 260mm^2,750MHz 时峰值浮点性能为 240 GFLOPS(双精度)或者 1200 GFLOPS(单精度)。
不仅如此,现在 GPU 的带宽也是 CPU 所无法媲美的,例如 RADEON HD 4870 的内存带宽就是 115.2GB/s,而 Nehalem 搭配 DDR3-1066 的内存带宽也就是 26GB/s 左右,在内存容量方面,GPU 也正在迎头赶上,例如 NVIDIA Tesla 1060 就拥有 4GB 的卡载内存。
不过 GPU 内存子系统虽然有非常高的带宽,但是它的时延是非常高的,这主要是因为 GPU 主要针对的计算一直以来都比较少出现数据复用(data re-use)的情况,或者说局部性较差,因此基本上只是靠一小块的 FIFO(先进先出)作为缓存。
对于一些可能复用的地方,例如纹理过滤操作,就会采用比较简单的 read-only cache,不过庞大的多线程才是 GPU 克服内存时延的最大关键所在。
随着 GPU 踏足通用计算,data re-use 的场合越来越多,即使是现在游戏图形运算中时常遇到的 post processing,data re-use 也是司空见惯的事情,为此 GPU 厂商也都往 GPU 里加入可读写的软件管理 cache。
最早引入该概念的产品是 NVIDIA 的 G80,它有 16 个内核(称之为 Streaming Multiprocessor,或者简称 SM),每个内核内都有一块 16KB 大小、时延为 1 个时钟周期、具备 16 个 bank 的 SRAM,开发人员透过 CUDA 或者未来的 Compute Shader、OpenCL实现对这块 SRAM 的控制,而内核执行的线程结果可以在这里暂存实现高效的 data re-use。
到这里大家应该都很清楚从技术的角度而言,CPU 和 GPU 的发展都正面临着一个拐点,前者因为各种原因不得不延缓“ILP/频率”这个免费午餐而转向多核技术,而后者因为制造技术的发展所新加入的晶体管构成的功能模块不仅仅限于可以在图形渲染上使用,包括不少可以并行化的运算也都能拿到 GPU 上高效的执行。
这也就连带产生了市场争夺的问题。在很长的一段时间里,超级计算机、服务器这类被称作现金奶牛的市场都是由传统的 CPU 厂商提供运算部件,现在 GPU 厂商也要插一脚进来,他们在性能上的竞争力实在不容小瞥,而且已经有了一些现成的案例。
这不仅仅是高性能运算领域的问题,在以产量著称的桌面领域,GPU 涉足的通用计算也越来越让 CPU 厂商感到不少的隐忧,例如物理加速、视频处理、三维成品级渲染这类以往需要大量运算资源来完成的任务,GPU 厂商也都开始提供解决方案。
目前的 PC 市场普遍被认为进入了成熟阶段,这意味着市场容量在短时间内爆发性增长的可能性不大,所以 GPU 侵蚀 CPU 传统优势领域的下场将可能是 CPU 的份额受到挤压。
对于一般的 design house(设计公司)类型 CPU 厂商来说,这似乎不是什么大的问题,因为他们在营运上的成本主要是研发,而对于垂直型 CPU 厂商(IDM)来说,CPU 份额的下降意味着自己的最强优势——产能将变成非常沉重的负资产。
要避免这个问题的发生,最好的办法就是自己也推出类似的产品,Larrabee 就是 Intel 的答案。
#p#副标题#e#
● 十字路口前的另一次选择
每个厂商都会竭力让自己站在最有利的位置上,IBM 有 Power Everywhere 的发展策略,Intel 作为 x86 ISA 的始创者自然也有自己的 x86 Everywhere 的算盘。
在历史上 Intel 曾经推出过若干款图形芯片,例如 80 年代末期的 i860,90 年代末的 i740,其中前者对部分读者可能不怎么熟悉,但是当年它的推出其实是引起了不少的轰动,在介绍 Larrabee 的时候我觉得还是有必要提一下这个东西。
在 1989 年的 Comdex 大展上,时任 Intel CEO 的 Andy Grove 罕有地没有发表任何演讲,根据后来发表的一些书籍指出,其原因之一在于 Intel 内部正对 RISC 和 CISC 未来的地位展开激烈的讨论,而 Andy Grove 正受到这个争论的困扰。
在当时有各种形形色色的 RISC 预言,例如“在 2005 年你会购买一台 MIPS 芯片的 PC,而你的邻居则会购买一台有 SPARC 芯片的PC”,“486 是 CISC 的黄金时代,但是它还可能是最后的一枚 CISC 处理器”,“586 是最后一枚真正的 CISC 处理器”。
不过 Intel 此时手上除了已经被确定为 386 替代品的 486 外,还有一个 RISC 处理器,这就是 i860。
1986 年,当 Intel 内部已经笃定 486 为 386 换代产品的时候,一位在 Intel 内为 RISC 呐喊了 4 年的工程师 Les Kohn 知道这是无法改变的现实后,决定改变方向,向 Intel 高层提供一个“为 486 设计”的基于 RISC 的协处理器方案——i860。
在 386 时代,Intel 也提供了与 386 配套但是单独出售的 387 协处理器,能够为 CAD、3D 工作站提供 386 10 倍以上的浮点性能,在这个产品上 Intel 获取了丰厚的利润。协处理器能赚钱,赚很多的钱,所以 i860 作为 486 协处理器的赚钱期望让 Intel 终于通过了 Les Kohn 的建议。
然而 Les Kohn 和他的团队的实际设计目标却是推出一个与 x86 家族截然不同的产品,i860 属于不折不扣的 RISC 处理器,但是与 387 和 386 的差别相比还不算太大,Les Kohn 的目标是希望 Intel 最终能比较愉悦地接受 RISC 的概念。
Intel 的 387 协处理器针对的是 3D、CAD、工作站用户,这类应用的用户对性能的追求高于对兼容性的追求,在当时看来 i860 的确是一个不错的 Intel 涉足 RISC 的突破口。

最终设计出来的 i860 是一枚 64-bit RISC 处理器,拥有单周期双指令发射能力以及集成了一个 3D 图形单元,与其它 RISC 处理器相比,比较特殊的是这枚 i860 在内存管理上复制了 386/486 的换页机制,这有助于 i860 能比较容易地运行为 386/486 编写的 C 代码,从纸面规格上上来看的话,i860 远不仅仅是一枚协处理器而是一枚比一般 RISC 处理器更加强大的产品。
i860 和 486 一样都是一百万枚晶体管,但是在理论浮点性能和图形性能上 i860 都远优于 486,这看上去 RISC 的确存在一定优势。
但是 i860 最终没能取得市场上的成功,这牵涉到多方面的原因,而最致命的原因却是从一开始就已经的被决定了:Les Kohn 要设计的实际上并非是一个能够赚钱的产品。
和 x86 相比它缺乏软件支持,而几乎当时所有的工作站厂商都选择了开发、设计自己的芯片,此外它的实际浮点性能也与设计目标相距不少距离,ALU/FPU 的切换需要花费大量的时间,使得它无法成为真正意义上的CPU,更多的是作为它当初被举荐时候的"想法"——工作站图形加速器使用。
i860 乃至以后的 Pentium Pro、Itanium、Netburst的发展证明,Intel 一直都没有把所有的鸡蛋放在同一个篮子里,与这些架构并存的一直都有被证明是成功的“旧架构”并存,486、Pentium、Pentium M 等,这得益于 Intel 强大的技术储备和研发资金来支撑,而其他处理器公司大都由于资金限制选择了孤注一掷的产品研发模式。
在 Intel 推出 Larrabee 之前,曾经生产过一枚代号 Polaris 的 80 核处理器,这个芯片是被作为未来 Intel many-core 计划的原型来设计的,片上内核的数量、内核间的连接方式、高带宽的 3D Stack 内存实现是这枚芯片的主要试验目标。
80 个内核、成本高昂的 2D Mesh(网面式)内部连接网络、3D Stacked 内存等一系列在 Intel 历史上从来没有真正尝试过的技术都在这枚 Polaris 实现了,然而这些试验的成果可能由于时间的关系以及成熟度、可行性等原因,并没有没反映到 Larrabee 上。
按照 Ars Technica1 的报道,Larrabee 采用的内核是基于 x86 的 P54C(80502)。而历史上的 P54C 架构上属于 P5 的 debug 版,早于支持 MMX 的 P55C(80503)。根据这篇报道,当年 Intel 完成 Pentium 的设计后,交给了美国五角大楼,五角大楼将其用于耐辐射的军事用途。
而五角大楼有自己的半导体工厂来生产这些军用的 P54C,由于苛刻的应用环境,五角大楼还对 P54C 的 RTL(Register Transfer Level,逻辑综合)代码进行了彻底的除错,当若干年后这个军品版 P54C 完成了历史使命后,五角大楼将清理好的代码交给了 Intel,这就是 Larrabee 内核的来源。
更确切的事实来自于 Intel 于 Siggraph 08 发表的 "Larrabee: A Many-Core x86 Architecture for Visual Computing" 一文中所指出的:
Larrabee’s scalar pipeline is derived from the dual-issue Pentium processor, which uses a short, inexpensive execution pipeline.
对 Intel 来说,x86 的软件价值实在是其最大的资财,在历史上它替 Intel 战胜了几乎所有的桌面电脑、工作站、小型机处理器厂商,甚至包括 Intel 自己采用其他 ISA 的产品。
这次来自 GPU 的挑战在 Intel 看来不过是当年 RISC vs. CISC 争战的延续或者翻版而已,采用基于 x86 的 many-core 也许可以应对这样的挑战,而这也是对自己最有利的方案。
#p#副标题#e#
● Larrabee——体系架构概况
虽说 Larrabee 与 P54C 有一定的关系,但是从实际的体系架构来说,我们认为两者实际上是存在巨大的差异,对 Intel 来说 x86 的引入只是为了能发挥其既有的传统软件优势,为未来 many-core 的大规模导入进行预演,而在当下 Larrabee 首先必须作为 GPU 推向市场,这样才能有利于普及产品,这是非常重要的一步。

Larrabee 可以有多种配置形式,上图为 16 核版本的架构图
Larrabee 是由许多个 in-order(顺序执行)的内核以及纹理单元、内部环路、内存控制器、总线控制器等单元组成,具体的组合形式取决于针对的应用场合,例如作为 GPU 的时候就会整合进 PCIE 作为总线界面,如果是应用于主板上作为协处理器使用的话,还会整合进 QPI 界面。
在 Intel 的 SIGGRAPH 08 论文中提供了一份 65nm Core 2 Duo 处理器与同样制程但是支持 Multithread(4 Thread) 并具备 16-way SIMD 向量单元的 Pentium 内核更新版的对比,用来说明采用 in-order 执行的流水线在吞吐先决的场合在同样的面积、耗电指标下所具备的性能优势。
| CPU | Core 2 Duo | 类似 LRB 的 Pentium 更新版 |
| 流水线设计 | 乱序执行[OoOE] | 顺序执行[In-Order] |
| 内核数量 | 2 | 10 |
| 各内核单周期指令发射能力 | 4 | 2 |
| 各内核 VPU 运算能力 | 4 | 16 |
| iL2 cache 容量 | 4MB | 4MB |
| 各内核单指令流吞吐能力 | 4 | 2 |
| 共计向量吞吐率 | 8 | 160 |
代号 Conroe 的 65nm Core 2 Duo 芯片面积大约是 143 平方毫米,不过在耗电方面, Conroe 有多种频率规格,而频率与功耗是存在一定的正比关系,在无法确知 Intel 所谓的同样功耗情况下其实是指什么频率规格。
真正的10 个 Larrabee 内核实际上是没有那么大的 L2 cache 而且是有 FMADD 指令支持的。Larrabee 也不仅仅只有“内核”,还有内存控制器、外部总线控制器、纹理单元、内部环路等组件,这些组件毫无疑问也是需要占用大量芯片面积。
做一个对比好了,如果单纯计算所谓的内核,NVIDIA 65nm GT200 30 个“内核”占的面积大约是 148.8 平方毫米,是整个芯片面积(583.2 平方毫米)的 25%。
我们其实比较难直接对比上表中两者的浮点性能,表格中能反映的只是 Core 2 Duo 和 10 个类似 Larrabee 架构的内核但是并不实际存在的东西的浮点指标对比,不过从向量吞吐率指标来看,两者在同频率下的差别的确较大。
之所以如此,是因为 OoOE 的内核主要是为了追求指令级并行(ILP),有非常复杂的指令控制单元,而 in-order 在这部分上的处理比较简单,随着多线程技术的引入, in-order 可以把更多的资源放在扩展数据级并行(DLP)和线程级并行(TLP)上,提供比 OoOE 流水线内核更强大的向量吞吐率。
OoOE 流水线与 in-order 流水线各有特色,前者能维持较高的 ILP,但是流水线的复杂度较高,而后者的流水线复杂度低不少,能够在同样的面积、功耗下透过向量技术、多内核、多线程以及适当的固定功能硬件电路等措施加持达到非常高的浮点运算吞吐率。
这使得 in-order 流水线在几乎所有浮点运算吞吐先决应用场合中成为首选,例如所有的 GPU 以及 XBOX 360 的 Xenon、PlaystATIon 3 的 Cell、SUN 的 UltraSPARC-T1/T2 等等。
Larrabee 糅合了许多目前类似产品的特征,同时结合 Intel 自己的优势,加入了诸如 x86、SMT、QPI、大容量 cache 等技术,再赋予 Intel 强大的软件开发支持,力图成为一个 many core 时代的标志性产物,我们下面给大家进一步介绍其架构细节。
#p#副标题#e#
● Larrabee——内核与 Cache

上图就是 Larrabee 其中一个 CPU 内核、内部互连网络、该内核所属的 L2 cache 局部子集。
Larrabee 内核的指令解码器能转译标准的 Pentium 处理器 x86 指令、x86-64 指令以及专门定制的 VPU 指令(LRBni)。
为了简化设计,标量单元和向量单元都有自己独立的寄存器,彼此的数据传输/交换是需要先写入到内存,然后再读回到 L1 cache 里才能完成。
Larrabee 的 L1 cache 可以让标量单元和向量单元实现对内存的低延迟高速缓存化存取,结合向量单元(VPU)的 Load 操作就能让 L1 cache 像是一个扩展的寄存器堆,让许多算法的性能得到显著的提升,尤其是使用 Larrabee 提供的 cache 控制指令。
Larrabee 的内核具备 SMT 多线程技术,为了让这 4 个硬件线程得以充分发挥性能,Larrabee 内核的 L1 指令 cache 和 L1 数据 cache 从 Pentium(单线程)的 8KB+8KB 扩展为 32KB+32KB 了,这恰好是匹对线程数。
Larrabee 拥有一个基于目录式一致性设计的二级高速缓存(L2 cache),每个 Larrabee 内的 CPU 内核都在这个 L2 cache 内有自己对应的区域,这个区域的大小为 256KB。
所谓的“一致性”简单来说,就是指在一个存储器系统中读取任何一个数据项返回的结果必须确保总是最近写入的数值,在单处理器环境中这个问题很简单,但是在多处理器的情况下,由于各个处理器很多时候都有各自独立的 cache (Larrabee 就是这样),那么情况就会复杂许多,而不同的一致性协议设计对性能都有直接的影响。
一致性协议最常见的就是监听式和目录式,监听式需要较高的的总线带宽,一般只用在小规模的多处理器系统中,而像 Larrabee 这样多达 32 内核的设计,如果使用监听式协议的话,内部总线的成本将非常高。
故此 Larrabee 的 L2 cache 采取了目录式的设计,当然这也和 Intel 已经掌握了丰富的 cache 一致性设计经验有关,而像 NVIDIA 这样的 GPU 厂商在可读/写 cache 上的设计经验与 Intel 相比就可能有较大的差距。
Larrabee 的每个内核都有连接到自身 L2 cache 子集的直达通道,因此各个内核能够一起并行地对自身 L2 cache 子集进行访问操作。内核所写的数据会被存储于自身的 L2 cache 子集内并在必要的时候可以被其他内核对应的 L2 cache 子集所冲刷掉。Larrabee 的内部环状总线网络能确保共享数据的一致性。
#p#副标题#e#
● Larrabee——标量单元与 cache 指令
Larrabee 的标量运算单元实际上就是衍生自 Pentium 处理器的双发射超标量流水线,同样存在类似 Pentium 那样的 U、V 两条流水线,其中的主流水线和 SIMD 16 路向量单元共享部分资源。
标量单元能支持 Pentium 处理器的所有 x86 指令,可以运行对应的操作系统内核和应用程序,主要的区别是加入了 x64 指令、新的标量指令例如 bit count/bit scan 、cache 控制指令和 4 个硬件线程的执行能力。

Larrabee 新引入的 cache 控制指令和指令模式能够实现显式的 cache 控制,例如可以实现往 L1、L2 cache 预取数据的指令和降低 cache line 优先权的指令模式。
流式数据通常很快就会把 cache 内的数据挤兑掉,Larrabee 能够在每条流式数据的 cache line 被访问后进行标记以便提前清空。这些 cache 控制指令同样允许 L2 cache 可以像一个擦写板内存(scratchpad memory)那样使用的同时实现完全的一致性,对于提高性能有莫大的裨益。
对于 Larrabee 单个内核内而言,透过多个线程来对 shared memory 进行同步存取的代价并不高。位于单个内核的线程共享相同的本地 L1 cache,因此在 L1 cache 内就能满足完成一个单独的原子旗语读取。相较而言,多个内核之间的同步存取成本就要高多了,因为这需要透过处理器之间的锁定来实现,当然这是一个多处理器设计中众所周知的难题。
多指令发射 CPU 的性能损失通常是由于难以找到能一起匹配执行的指令。按照 Intel 自己的测试,Larrabee 的双发射解码器拥有较高的多发射率,主、副指令流水线的匹对原则在这里起关键性的作用,它允许编译器在比一个运行时式的乱序指令采集器更宽的范围内进行离线分析。
所有的指令都能发射给 Larrabee 标量单元的主流水线执行,这让编译器的指令合并难题降低到最低。而次流水线能够执行 x86 的大多数标量指令(包括 load/store、简单的 ALU 操作、cache 处理)以及向量 store 指令。
编译器毕竟不是万能的,对于编译器无法实现并发的代码调度造成的阻塞问题,Larrabee 的 4 硬件线程执行能力可以在一定程度上予以掩盖。当数据不能预先预取至 L1 cache 而需要从 L2 cache 装载至 L1 cache 造成的时延问题,硬件多线程执行同样能予以掩盖。当在相同内核上使用相同的数据组时,运行多个线程同样能提高 cache 的效率。
#p#副标题#e#
Larrabee 向量单元(VPU)的最高向量处理宽度为 16,可以执行整数、单精度/双精度浮点指令,Intel 专门找来了多为业界的资深开发人员一起协作开发专门针对 Larrabee VPU 的指令集——LNI。
VPU 加上它的寄存器所占的面积约只相当于单个内核面积的 1/3,但是它所提供了 Larrabee 的绝大部分性能。

Larrabee 的 VPU 是一个 16-路宽度的 SIMD(单指令多数据)向量处理器,按照 Intel 的说法这是在高运算密度和运算单元利用率上的一个折衷选择。
依照 Intel 的早期分析,如果采用 16-路单元一次处理 16 个像素单个组元,即采用分离的指令分别处理像素中的红、绿、蓝等组元而不是一次合并处理像素的多个色彩组元,在这样的方式下典型像素着色器程序(pixel shader)的演算效能可以达到 88%。
Larrabee 的 VPU 指令支持 3 个源操作数,第一个源操作数以及目标数是同一个而且通常必须位于向量寄存器中(某些指令中,头两个源操作数的第一个必须是 mask revister),但是指令中的最后一个源操作数可以来自于“内存”,如果数据已经预取至 cache,那么此时的 L1 cache 可以看作是一个扩展的寄存器堆(register file)。
对于 madd 以及 multi-sub 指令,第一个源操作数既是源数也是目标数,因此它们都没有非破坏性的形态,只有用于专门设计用于内插 vmadd233 指令是例外。
VPU 可以读取自 cache 的数据类型包括了 8-bit unorm、8-bit uint、16-bit sint 以及 16-bit 浮点数据,它们都能在不损失性能的情况下被转换为 32-bit 浮点数或者整数,由此可以显著增加可存储于 cache 内的数据类型并降低单独数据转换指令的需要。
Larrabee 向量寄存器中的数据可以多种方式在排列上进行对调(即 Swizzle 或者 Re-Order),以达到可以对正 VPU 处理单元通道的需要。位于 cache 内的数据可以直接“复制(Replicate)”到 VPU 的单元通道,这个功能可以在图形运算和非图形运算的时候使用,能显著提高 cache 的利用效率。
Larrabee 的 VPU 能支持多种类型的浮点、整数数据指令,指令集提供了标准的算术操作(例如 fused multiply-add)、标准的逻辑操作(例如从像素中提取出非字节对齐的栏位),这些都是属于从寄存器或者内存读取并把结果写入到向量寄存器的 load-op(装载操作)的指令。
配合 load/store 指令,VPU 就能支持在大多数 GPU 中一些较少见或者更复杂的数据格式与浮点值之间进行转换的操作,对这类操作采用分离指令或者说软件执行的方式可以显著地节省芯片面积和电力消耗,而代价只是些微的性能损失。
VPU 的指令还支持 gather 和 scatter 式的操作,允许往非连续的地址进行 load 或者 store 操作。VPU 的 16 个数据元可以自 16 个不同的向量寄存器地址进行 load 或者 store 操作而不是只能在单个的向量寄存器地址上进行。
这两个功能的实现可以让 VPU 的 16 个运算单元并行地执行 16 个 shader instance,而每个看起来像是在串列的方式来执行,甚至在使用运算出来的索引来执行数组存取的时候也能如此。
gather 和 scatter 的性能受限于 cache,因为每个周期 VPU 只能 load 或者 store 一条 cache line,如果地址分布在若干 cache line 里,那么就需要若干次的 load/store,使得 gather 和 scatter 的性能大打折扣,例如地址分布在 16 条不同的 cache line 内就必须需要 16 个周期才能完成一次 gather 或者 scatter 。
按照 Intel 的说法,由于许多工作负荷都具有高度的连贯性存取样式,因此 gather 和 scatter 的存取周期要远低于 16 个周期。
透过一个 mask(遮罩)寄存器(VPU 的每个运算通道都对应一个位元的遮罩寄存器),Larrabee VPU 指令执行能够被予以论断(predicate)。这个 mask 控制向量寄存器或者内存位置哪些部分被写或者不被更改。
举例,一个标量的 if-then-else 控制结构能够透过一条指令来设置 mask 寄存器以基于比对的方式映射(map)至 VPU,而后 VPU 以 mask 寄存器控制的相反极性既执行 if 从句部分也执行 elsa 从句部分,而不管运算完成后是否写入结果。

|
;if (v5vcmppi_lt k7, v5, v6 |

以动画形式展现上面的简单分支程序如何在 Larrabee 上被执行,只有 mask register k7 为 1 的通道的数值才会被完整保存,k7 为 0 的通道的数据均被写入 1。
当 mask 寄存器内都是 0 或者 1 的话,条件从句能被完全地中止掉。这样能够减少少数从句出现分支预测失败而遭遇的性能惩罚,同时也让编译器的指令调度器有更高的自由度。
VPU 同样使用这些 mask 寄存器来给 load/store 指令打包,从而在连续的内存地址中访问允许的数据元。这样程序员就能在满足复杂分支条件的情况下整合稀疏的执行 strand(缕程),使其成为一个能更有效实现向量计算的格式。
按照目前公开的 Larrabee 指令集架构资料,VPU 的 mask 寄存器数量是 8 个,寄存器位宽是 16-bit。
#p#副标题#e#
● Larrabee——处理器内部连接环型总线
Larrabee 采用了双向的环形总线网络,允许芯片内的代理(Agent)例如 CPU 内核、L2 cache 以及其他逻辑模块彼此沟通。如果 CPU 内核的数量超过 16 个的时候,就会采用多个短连接环型总线来挂接,这个结构被称作 X-Ring。
每条环形数据总线的各向位宽是 512-bit,所有数据的行程安排都是在注入信息至环形总线之前就已经确定。例如,每个 agent 能在双数周期的时候从一个方向接纳一个信息包,在奇数周期的时候从另一个方向接收另一个信息包。
这样的安排能简化环形网络的路由逻辑,当数据出现在网络上时,这些数据无需被保存在路由器单元中,从而可以实现在非常小的代价下提供竞争最小化的高带宽。
Larrabee 环形网络最初的设计是把 L2 cache 和 内核都作为 agent 挂在总线上,以方便实现一致性,但是这样带来的问题是对 Larrabee 来说,环形总线面临的传输压力极大,结果这个设计很快就被抛弃了。现在 L2 cache 配属给每个 Larrabee 内核,成为 内核的一部分,应用先进的一致性协议以及 cache 控制指令,确保总线的压力尽可能地低。
Larrabee 的 L2 cache 被设计为每个内核可以高带宽地存取没有被其他内核写入结果的内存地址,因此每个内核的数据都是保存在自己对应的 L2 cache 子集部分内。各个内核可以并行地存取自己所属的 L2 cache 子集,而无须与其他内核进行通信。不过,当在 L2 cache 中分配一条新的 cache line 时,环路网络会被用于检查数据共享,以维持数据的一致性。
这个处理器内部网络本身也是作为一个 L2 cache 存取内存的路径。一个典型的高端产品会包括多个标准设计(例如 GDDR3、GDDR5)的内存界面,这些内存界面分散挂接于处理器内部网络上的若干处以降低拥挤度。
在片上网络环绕的延迟会增加内存存取的时间,但是相对于存取外部内存的延迟,额外的环路延迟通常显得非常低。
Larrabee 的 CPU 内核可以透过这个片上的环形网络总线对固定功能单元进行访问,而后者也可以访问 L2 cache 和内存,和内存控制器一样,这些固定功能单元分散地挂接在环形网络的若干处以降低存取竞争。
#p#副标题#e#
● Larrabee——功能固化单元
现在的 GPU 包含了若干功能固化逻辑单元用于不同的图形运算任务,例如纹理过滤、显示输出处理、后着色器阿尔法混合、光栅化(rasterizATIon)以及内插等。
光栅化在这里仅是指确定一个图元(primitive)覆盖的 fragmet(片元)位置以及依照图元的覆盖样本位置参数值进行内插的动作。
功能固化单元通常需要若干 FIFO(先入先出)缓存实现负载平衡,这会导致难以在避免浪费芯片面积和性能瓶颈的情况下正确地确定这些逻辑电路及其 FIFO 缓存的大小。
Intel 对 Larrabee 的设计理念是只要软件执行方式的性能足够,相应的功能固化单元就采用软件执行方式取代。例如,Larrabee 上就没有包含光栅化、内插或者后着色器阿尔法混合等功能固化单元,使得 Larrabee 可以增进新的功能和最佳化措施,被取代的任务可以在渲染流水线不同位置执行,取决于具体的应用程序在什么情况下能达到最高效率。
采用软件方式执行后 Larrabee 可以依据它们对性能的需求进行运算资源分配,而不是设计一些为了攀爬峰值性能的硬件电路。

Larrabee 保留了纹理过滤单元,原因是 Larrabee 的内核还不能高效的执行纹理过滤操作。根据 Intel 的分析,在 Larrabee 的内核上以软件方式执行纹理过滤操作,性能只有 Intel 自己设计的纹理单元的 1/12~1/40,性能幅度取决于是否启用了纹理解压缩。
对此,Intel 将原因归结为 4 点:
-
纹理过滤依然普遍采用 8-bit 色彩组元,这类组元在专用电路上处理比 32-bit 宽的 VPU 运算通道更有效。
-
要高效选择未对齐 2x2 四方图块进行过滤处理需要一个特定流水线类型的 gather(聚集)电路。
-
读取纹理数据至 VPU 用于过滤处理造成的寄存器堆带宽压力近乎不可行。
-
在专用硬件上执行即时纹理解压缩的效率要远远高于 CPU 内核。
Larrabee 的纹理过滤单元在内部特征上和典型的 GPU 纹理单元相当类似,每个 CPU 内核拥有 32KB 纹理 cache ,纹理单元可以支持所有的常见操作,例如 DirectX 10 已压缩纹理格式、mipmapping、各向异性过滤等。
Larrabee 的内核透过 L2 cache 向纹理单元发送指令并透过 L2 cache 接收纹理单元的运算结果。纹理单元和内核使用同样的 x86 虚拟内存页面。纹理单元执行虚拟至物理页面转换并向 Larrabee 内核报告所有的页面缺失,当页面在内存的时候,内核发回纹理过滤指令给纹理单元。
只要软件执行方式的速度足够快,Larrabee 也可以直接使用其 CPU 内核执行纹理操作。
#p#副标题#e#
● 进行图形渲染的多种途径之一
Larrabee 本质上是由若干 CPU 内核构成的 many-core (众核或者说群核)处理器,理论上可以采用几乎所有风格的渲染方式,但是前提是必须能实现高度的并行化,Intel 在 Larrabee 的论文中阐述了基于 sort-middle 方式的软件图形渲染器,采用 binning(分仓)来实现负载平衡来实现高效的图形并行处理运算。
什么是 sort-middle?
所谓的 sort-middle 是相对 sort-first、sort-last 而言,sort 在这里指的是从模型空间转换为屏幕空间。

Sort-first 是在图形渲染流水线的开始阶段就将图元(primitive)分配到各个渲染节点,一般用于多屏输出或者像 AFR、SFR 这样的多 GPU 渲染方案;sort-last 是在光栅化后重新分布像素;而 sort-middle 则是在几何变换(geometry transform)与光栅化之间重新分布图元。
sort-last 和 sort-middle 比较符合图形流水线的自然形态,适合硬件实现,SGI 的 Reality Engine、Infinite Engine 属于 sort-middle;大多数的 GPU 以及 NVIDIA NVSG-Scale 的多 GPU 渲染方案都属于 sort-last 中的 sort-last fragment。
除了这三种主要的 sorting 方式外,还有其他的 sorting,例如将三种 sorting 混合的方式。
关于 sort-first 和 sort-last,大家可以参阅 NVIDIA NVISION08 上的一篇幻灯片:NVISION08-Does_Your_Software_Scale.pdf
基于 sort-middle 模式的渲染器大致可以分为 Tile-based(拼图式或者说图块式)和 Interleaved-based(隔行式)两种,SGI 的 Reality Engine 属于 Interleaved-based,而 ImgTech 的 PowerVR 以及 ARM 的 Mali 都属于 Tile-based。
RTset 的定义
在 Intel 的文档中,Larrabee 采用的是 Tile-Based 的渲染方式,我们以假设渲染一组单独的 render target(渲染对象)(例如一个像素缓存和一个深度缓存)为例简单介绍 Larrabee 的渲染原理。
在 Larrabee 中这些 render target 以及对他们进行更动的渲染指令一起被称作 RTset。
Primitive Set 的定义
RTset 的渲染指令通常由图形 API 所定义一系列遵照当前设备状态对一个三角形 batch (批组)渲染时的渲染状态变化。Larrabee 渲染器并不采用当前本性状态的观念,而是采用在单一完整定义的结构中捕获渲染状态(这里所谓的单一完全定义结构简单来说就是指一个 Tile)。
而后 Larrabee 将三角形的 batch 分组并依照使用状态对每个 batch 打上 tag(标签)。这些是三角形的 batch 及使用状态被称作 primitive set (图元集)或者 PrimSet,大致相当于 Direct3D 里 DrawPrimitive,不过两者并不完全对等。
RTset 的渲染与 tile、bin 的定义

上图就是 Intel 提供的对单个 RTset 的 PrimSet 进行渲染的大致流程。渲染的画面被切成若干像素组成的 tile(图块),每个 tile 都有一个 bin(图元仓)来放置 PrimSet 中与该 tile 交叠的三角形。对应整个 RTset 的 bin 被称为 bin set。有时候 tile 和 bin 在术语上是相通的,不过在这里 tile 是指实际的像素数据,而 bin 是指映射至 tile 的 primitive set(图元集)。每个 tile 都有一个 bin,bin 内放的是与之对应的 tile 内交叠的三角形

简而言之,每个 tile 都有一个 bin,每个 RTset 都有一个单独的 bin set。
除了三角形外,bin 内还保存有已经着色的顶点、完成光栅化的 fragment(片元),所有的 bin 都保存在片外的内存(例如显卡内存甚至系统主内存)上。
Tile 的尺寸与性能影响
每个 tile 的大小是依据 RTset 的目标表面来设置:tile 的尺寸要能完全放置到 Larrabee 内核的 L2 cache 里。因此,相对使用较少、较低色彩通道的 RTset, 一个有许多色彩通道或者使用高精度数据格式的 RTset 所采用的 tile 尺寸就更小了。
为了简化代码,tile 的尺寸通常是正方型或者平方数,典型的大小为 32x32 至 128x128。
如果采用 32-bit 深度和 4D*8-bit 色彩的话,一个 128x128 的 tile 只会占用 256KB L2 cache 的一半空间,如果是 32-bit 深度,4D*32-bit,就可能需要把 tile 尺寸降低到 64x64,因为 128x128 32Z+128C 占的空间已经撑爆掉 L2 cache。
只要 tile 能完全放置在 L2 cache 内,即使是不同尺寸的 tile 渲染速度都不会有显著的波动。
尺寸较小的 tile 面临的的问题主要是场景中的某些三角形会在多个 tile 上交叠,因此每个被交叠 tile 都需要对这些三角形进行处理,术语上这被称作 bin spread (图元仓跨界)。Tile 越小出现 bin spread 的机会就越高,不过按照 Intel 的说法,在现在的渲染应用中出现 bin spread 的机会小于 5%,这意味着需要重复处理的跨界三角形数量相对单个覆盖整个 render target 的 bin 来说少于 5%。
渲染阶段概说
渲染处理过程分为两个阶段:front end (前端)和 back end(后端)。
在 front end 阶段,每个 PrimSet 都会被赋予一个序列 ID 用来识别在 render stream 渲染流中它在哪里会被提交。在 back end 阶段,这些序列 ID 就会被用来做 ordering(排序)。
PrimSet 被分配至一个内核中,执行 vertex shading(顶点着色)、tessllATIon(镶嵌/拆分)、geometry shading(几何着色)、culling(剔除)、clipping(剪切)来生成三角形(或者其他图元)。
内核对每个三角形进行光栅化处理并测定它覆盖的是哪一个 tile以及它覆盖的是这些 tile 中的哪个样本。这个过程计算的结果是一系列 x、y 轴坐标以及对应每个三角形的样本覆盖遮罩。数据结果连同顶点数据参考的索引保存于 bin 内。
一旦 RTset 的所有 front-end 处理完成并且每个三角形都被加载到覆盖到的 tile 所对应的 bin 后,back-end 阶段就开始执行。每个 tile 都会被分配到一个内核中,内核对所对应的 bin 内的三角形进行着色处理,包括向纹理单元请求纹理样本。Back-end 还处理深度、stencil(镂版)以及混合操作。
和 ImgTech 的 PowerVR 不同的是,Intel 所举这个的 Larrabee 渲染器例子虽然是 tile-based,但是却并没有在着色处理前执行“完美”的 occlusion culling(闭塞剔除)、着色重排序以及其他任何的非标准渲染方法。
在从 DirectX、OpenGL 指令流获取指令的时候,单个 tile 的渲染是依照应用程序的指令递交次序进行渲染的。在 tile 内采用传统的渲染流水线,能避免在众多现存应用中出现功能性、性能的意外问题,实现在现有的程序上拥有一贯的良好表现。
按照 Intel 的说法,front-end 和 back-end 的工作比例分别为 20% 和 80%,但是这个应该只是典型应用下的状况。
如何应对 Render Target 的相依性问题
每帧画面都是由每条发送至渲染表面的渲染指令依照一定的次序渲染而成。新式的应用程序在渲染一帧画面的时候可能会一次使用多个 render target 以达成一些诸如反射、shadow map 的渲染效果。
为了处理这些一帧画面内的不同 RTset,Larrabee 的软件渲染器先要为 RTset 对应的每个节点创建对应一个 graph(关系图),而后每个节点会被分配到变更其 RTset 的 PrimSet。
当一个 RTset 使用一个 render target (例如一张纹理)于另一个 render target 的后续渲染操作时,两个 RTset 之间就建立起了相依性。
例如在渲染 shadow map 的时候,场景的主要 render target(即 back buffer 和 depth/stencil buffer)就和应用于 RTset 上的每个 shadow map 存在相依性。

一旦相依性关系图创建完成,Larrabee 就能以符合相依性的任何顺序选择这些节点进行渲染。上图就是一个场景中两框画面的相依性关系图,在这个场景中需要渲染两张 shadowmap,为了简化关系图,我们没有把一号帧的 shadow map 关系放到关系图中。
在这个关系图中,大家可以看到,即使 1 号帧渲染完成,2 号帧的渲染依然需要需要等到 2 号帧的 shadow map 完成渲染以及 1 号帧结果拷贝至 front buffer(这一步是因为 1 号帧和 2 号帧的 back buffer 在内存位置上是相同的,假如位置不一样就可以免去这一步)后才能开始渲染 2 号帧的 back buffer 和 depth buffer。
不过 2 号帧的 Shadow Map 和 1 号帧是可以并行渲染的,因为它们没有相依性存在。
注意,只要顺序得以保持,RTset 关联的 PrimSet 能够根据需求被切成若干个子集。一个 RTset 如果太大无法让一个单元高效的地处理,我们也可以将它分割,例如提供更细的调度粒度。
并非所有的 Larrabee 的内核都需要同一时间对同一个 RTset 的 PrimSet 进行处理,这意味着某些以前 tile 架构中的限制由于现在 Larrabee 有能力任意分割、调度 RTset 而得以避免。
Front-End 阶段的顶点及几何体处理
由于图形渲染指令更动了状态,执行的次序就显得非常重要了。GPU 依照顺序执行这些指令,因此指令的开始和结束都是依序的。当渲染指令在输入的时候被并行化的话,它的输出结果必须依序重新排列。Geometry Shader(几何体着色器)的输出数目是变化的,这就要求相当大的 FIFO 缓存维持次序以及让阻塞最小化。
Larrabee 可以让前端以并行的方式处理多个 PrimSet,它有一个控制处理器确定哪一个 PrimSet 依照 RTset 的相依性关系图在任何特定的时间渲染,并且把这些 PrimSet 添加到 active list (运作列表)中。
Larrabee 内核不断地从这个 active list 中获取 PrimSet 来执行前端工作。每个内核使用其自己 tile 中 的 bin 子集,避免和其他执行前端阶段的内核产生 lock contention(锁定冲突)。
PrimSet 的次序 ID 被写到 bin 内,因此后端阶段能透过从有最小 次序 ID 的 bin 子集恢复原本的顺序。

上图展示了在 Larrabee 一个内核执行 front-end 的过程。
第一步是识别构成每个图元的 顶点。这一步可能会由于 index buffer 而变得复杂,因为 index buffer 允许随意映射一个顶点缓存内的顶点至图元,例如映射至高效存储的 mesh(网片体)。
第二步,被获取的顶点如果还没有进行 transform(变换)处理的话,就会被透过运行 vertex shader(顶点着色器)对它们进行 transform(变换)操作。被 transform 的顶点之后以 stream(串流)的方式输出至主内存。
除了位置数据以外的数值会从 L2 cache 中被主动清空,因为这些数据在进入 back-end 中进行 interpolATIon setup 的之前都不会再被使用。
在此之后 geometry shader(几何体着色器)就开动了,然后是 frustum cull(视域剔除)、back cull(背面剔除),最后是 clipping(剪切)。
Intel 提供的这个算法是在 front-end 进行覆盖范围信息,而后将其放入到 bin 内。这样的做法是为了确保良好的负载平衡,即使如果少数的 tile 包含了大量的三角形。
光栅化可以在 front-end 或者 back-end 上执行,又或者是分割开来在两个阶段执行,因为 Larrabee 是软件方式执行光栅化的。
软件光栅化及内插
RasterizATIon (光栅化)又被称作 scan conversion,在 Intel 的文档中仅限于指侦测哪个像素是位于三角形内(光栅化并不理会三角形外的像素),而 InterpolATIon(内插)是确定位于受覆盖样本的参数值。
Intel 没有为 Larrabee 配备专门的硬件电路来执行这个动作,而是完全依赖于 Larrabee 的 CPU 内核以软件的方式来执行,在这里就得提一段小插曲了。
Intel 为 Larrabee 动用了可说是空前的人力,除了招揽了业界顶尖的图形学科研人员到自己的旗下外,还在业界聘请了多个精英为其提供关键的顾问服务,这其中就包括了传奇人物 Michael Abrash。
Michael Abrash 的厉害之处在于长期以来一直擅长透过精密的指令执行分析,以创新的方式对程序进行精密的优化,具有宝贵的程序优化实践经验。
Intel 招募这样的重量级人马,自然是希望他以及他们能以游戏产业的专家身份,在 Larrabee 的研究阶段就 Larrabee 的新指令集结构提供意见,并在此基础上探讨出一些应用的实证,例如软件渲染器。
在 Larrabee 之前,Michael Abrash 所在的 RAD 公司就曾经开发过若干个软件渲染器(这个渲染器已经被 Intel 收购),而 Michael Abrash 以及其他分量同样很重的专家所面对的其中一个挑战就是光栅化操作的软件执行可行性。
一言蔽之,Intel 不希望在 i860 上由于脱离实际而遭遇到的惨况在 Larrabee 上再现。
Michael Abrash 表示在 Larrabee 之前曾经写过至少 4 个软件执行的光栅化器,但是性能都远远不及硬件执行。Michael Abrash 对此有过这样的描述:
"there was no way we could think of to add new instructions to speed up the familiar software rasterizATIon approaches, and no obvious way to vectorize the process, so we concluded that a hardware rasterizer would be required. "
在 Larrabee 架构的设计阶段,随着向量宽度和内核架构的不断变更,Larrabee 的其中一位架构师 Eric Sprangle 一直问 Michael Abrash 是否可以软件方式以向量处理执行光栅操作,这类提问据当事人回忆,达到了"数以百计"。
从架构师的角度出发,力图确保 Larrabee 尽量减省功能固化单元是最为重要的设计目标之一,因此这样的提问是合情合理的。
Michael Abrash 和另一位 Larrabee 的软件/硬件架构师 Tom Forsyth (曾经和 Michael Abrash 一样在 RAD 公司工作,还在 3DLabs 公司编写过 D3D 驱动,此时已经加入 Intel 公司)由于有之前从事底层 3D 开发工具的经验,自信深谙其中的问题所在,因此一直很努力地向 Eric Sprangle 解释这是行不通的。
直到有一天,Eric Sprangle 说道:“看,我们现在用 P54C 内核了,你们觉得软件光栅化可行了吗。”
Michael Abrash 对这样的问题实在受不了了,因为在他(们)看来,内核的向量性能对光栅操作不会有重大的影响。被惹恼了的 Michael Abrash 等人和 Eric Sprangle 坐了下来,当场编写执行代码试图向后者详细地解释为啥这是行不通的。
不过 Michael Abrash 这次的尝试失败了,倒是反而证明了 Larrabee 的设计可以使用软件方式相对高效地进行光栅化操作,这段争论形成了 GDC 2009 上的一篇论文的基础。
说起光栅化,我们需要知道的是它的实现有多种方式,可说是千奇百怪。
例如 SGI 公司 Power Series GTX 采用的 Gouraud shaded、美国北卡罗纳州大学的 Pixel Planes 4 采用的 per-pixel 估测、SGI 公司 PowerVision (VGX)采用的 Edge walk+平面参数指派、SGI 公司 InfiniteReality 采用的重心直接估测、GDA Technologies 公司的 Bali 参考板 Freescale MPC5121e 处理器采用的 small tiles、NVIDIA 公司的 Homogeneous recursive descent。
Larrabee 的特点是 VPU 提供的强大向量处理能力,理论上可以对屏幕上的所有点逐个进行三角形覆盖估测,但是这样的动作其实挺浪费的,因为即使在一个 64x64 的 tile 内,有时候三角形的大小也都小于甚至远远小于这个 tile 的尺寸,对许多远离三角形覆盖位置的像素估测运算也就成了无的放矢,Intel 需要的是一个能节省资源(通常也意味着高性能)的软件实现方案。
对于这个问题,Michael Abrash 的团队决定采用被称作 bucket sorting 的方式先用三角形的 bounding box(周框方格)把三角形覆盖的 intra-tile(内块)找出来,然后再对这(些)个 intra-tile 进行实际的三角形扫描,找出覆盖的 fragment(片元),见下图。

这是一个大小为 64x64 的完整 tile(图块),我们以此来举例。由于每个 tile 每次光栅化处理只会处理一个三角形,所以在这个 tile 中有一个三角形。

我们把这个 64x64 的 tile 以 16x16 的大小再划分出 16 个 intra-tile(内块)。
Larrabee 的 VPU 一次处理一个 tile,而 VPU 的向量宽度是 16,因此能够一次完成对 16 个 intra-tile 的检测,不过我们在这里检测的不是具体的三角形,而是三角形的 bounding box,这是为了简化检测的计算复杂度。

经过 bit-scan 指令测定,我们发现这个三角形完全位于其中一个的 intra-tile,如上图。按照 Intel 的说法大约 90% 的三角形都是这样:一个 tile 就能容纳的小三角形。
在接下来的计算中,Larrabee 会把这个包含了三角形的 intra-tile 再划分成 16 个 4x4 block(方块)组成的计算矩阵。

对这个 Intra-Tile 采用类似的算法可以查出三角形覆盖着上图中的 5 个 4x4 block,图中用橙黄色方框标注。

上图就是对这 5 个 4x4 block 做光栅化的过程,如果需要进行 multi-sampling(多采样) 的话。例如 4x MSAA,那么对这 5 个 4x4 block 的光栅化处理就需要重复 4 次,MSAA 倍数越高,需要扫描的次数就越多,此时扫描的取样点位置也不再是像素的中心点,而是 MSAA 的取样点,以确保获取更接近精确的三角形覆盖位置信息。
在这里小三角形的例子中,我们可以看到,整个 tile 的光栅化处理实际上只需要对 80 个像素位进行三角形扫描,而其他的 4016 个像素位则不需要,但是需要进行大约两次的 not-rasterizATIon(非光栅化)来剔除掉不需要光栅化的 intra-tile 和选中的 intra-tile 内不需要光栅化的 4x4 block。
不过在实际的渲染中,除了上面说的小三角形的情况,还是会遇到不少大的三角形,这些大三角形有时候会出现前面我们介绍 tile 尺寸的时候提到 tile spread(图块跨界)现象,这时候就要执行 triangle assignment to tiles(指派三角形至图块)的处理,这个步骤需要 64-bit 运算。Larrabee VPU 的 64-bit 性能峰值是 32-bit 1/2 或者更低,显然这个处理消耗的运算、带宽资源要高出那些完全能放置在 tile 内的三角形所需的 32-bit 运算。幸运的是,Larrabee 的 tile 最高可以达到 128x128,90% 的三角形度能完全放置其中。
作为由多个 CPU 组成的 Larrabee 处理器,采用软件算法执行光栅化的确可以采用各种不同的优化策略,除了上面提到的层阶式处理,还能进行一些诸如在光栅化处理之前就把一些不可见的三角形剔除掉等进一步的优化措施,如果必要的话,整个 Larrabee 的所有内核都能被调动用于光栅化的处理。
需要注意的是,光栅化涉及到的方程式并不是一两条指令,因此我们上面简单的三部曲在实际处理的时候,每个三角形可能需要数以十计甚至数以百计的周期来完成,单纯从性能/芯片面积的比值上来说,Larrabee 的软件光栅化性能是不可能比得上专用硬件单元的。
Intel 对于光栅化的能力的自信一定程度上源自对一些当前实际游戏分析,在这些分析数据中,Larrabee 执行软件光栅化的处理时间占用比率大约在 3%~20%。
不过在 FEAR 中的 15 帧分析数据里,有部分帧的光栅化处理占用时间比值甚至达到了 40%。
因此在光栅化处理上,Larrabee 的最高端版本(32 核,3GHz)可能可以比较轻松地应付,而在中低端的版本上,光栅化的处理能力还有待观察。
#p#副标题#e#
● Back-end 像素处理
当 RTset 的 front-end 处理阶段完成了位于 bin 内三角形数据处理后,这个 RTset 就会被推到一个 active list(运作列表)中。执行 back-end 阶段处理的 Larrabee 内核会不断地从运作列表中获取下一个 tile,渲染位于该 tile 对应 bin 内的三角形。
Back-end 渲染软件能够使用许多在新式 GPU 上依赖固化功能单元执行的优化措施,例如 fast clear、hierarchical Z 以及 early Z test。Hierarchical Z 可以放在 front-end 执行,以减少存放至 bin 的 primitive(图元)数量。
Back-end 代码的启动是由 render target 的像素预取到 L2 cache 中开始的。所有的渲染动作都是在 L2 cache 中执行,直到 tile 内再也没有 primitive 需要渲染,而后渲染的结果就会写回到片外内存中。如此一来,不管这个 bin 中有多少重叠的 primitive ,这个 tile 内的像素就都只需要分别从主内存读取一次和往主内存存写一次。
在此期间,有两种优化措施也可以用于侦测来节省内存带宽。如果第一个命令 clear(清除)了整个 tile,那么片外内存的读操作就能节省掉。如果渲染后不需要深度数据并且 MSAA(多取样抗锯齿)在写入片外内存之前可以 resolve(求解)为每个像素对应一个色彩值的话,往片外内存的写操作也同样可以减免。

上图表示的就是在单个内核实现上高效执行多线程化 back-end。
首先一个 setup thread(设置线程)从 sub-bin(图元子仓)中为 tile 读取图元。
然后 setup thread 对各个顶点执行 interpolate 查找出个样本的数值。
最后,setup thread 把像素以 4x4 的 QQuad(四个四方)为一组发射至 work thread(工作线程)。Setup thread 采用 scoreboard(记分板)确保这些 QQuad 在所有重叠的像素完成处理之后才被递交给 work thread。
图中的三个 work thread 执行余下的所有像素处理,包括 pre-shader early-Z test(预着色器早期 Z 测试)、pixel shader(像素着色器)、post-shader blending(后着色器混合)。
新式的 GPU 采用专用的电路单元执行 post-shader blending,不过在 Larrabee 上则是使用 VPU来执行。这样的做法效率是非常高的,因为许多 pixel shader 程序并不执行 post-shader blending,因此专用的电路单元对某些 pixel shader 来说是没有用上的,而且对其他的 pixel shader 来说可能会对性能形成约束。
Larrabee 虽然的每个内核有 32KB texel cache 以及 256KB 的 L2 cache,但是涉及纹理操作的话还是很多情况下都需要访问片外内存的,由此而产生的数百周期内存存取时延是必须面对的。
对于纹理存取时延的问题,Larrabee 是尝试采用硬件 thread(线程)计算多个 QQuad 来予以掩盖。每个 QQuad 的 shader 被称作为一个 fiber(纤程),thread 里的不同 filter 相互切换,不需要操作系统干预。
当出现纹理读取指令的时候,fiber 的切换就会被执行,切换至运行于同一个 thread 上的其他 fiber。
Fiber 是以环形队列的方式执行。
对于 fiber 数量的选择,是按照 control flow(控制流)回到一个 fiber 的时间是否足够纹理访问操作完成并且该结果已经是可以准备用于下一步处理来确定。
#p#副标题#e#
● 早期性能模拟分析结果
在 Intel 在 Siggraph 08 上发表的 Larrabee 论文中,有一章专门提到了 Larrabee 的性能分析,是使用截取游戏数据流在一个模拟器上获得的,虽然不是实物测试结果,倒不失为一个参考。
在这个性能模拟分析中,主要包括了软件渲染延展性、与立即模式渲染器的带宽对比、不同渲染阶段的时间占用。
| 游戏 | Half Life 2 EP2 | F.E.A.R | Gear of War |
| 分辨率 | 1600x1200 | 1600x1200 | 1600x1200 |
| FSAA | 4 MSAA | 4 MSAA | No AA |
| 数据采集 | 25 帧(30 帧取 1 帧) | 25 帧(100 帧取 1 帧) | 25 帧(250 帧取 1 帧) |
Intel 的工程师首先以正常的速度运行游戏,截取地交给显卡的 DirectX 9 指令流以及每帧画面开初时纹理内容与渲染表面信息,透过功能模型测试这些信息流,确保算法正确获得正确的画面。
而后,Intel 的工程师抱着尽可能把各种潜在的糟糕因素与结果都考量进去的原则(即所谓积极的悲观主义),为每帧画面建立一个粗糙的 profile(特征属性文件)。对那些最慢的场景编写汇编代码,用周期级精密度的模拟器执行,将时钟周期结果送返功能模型,重新运行信息流记录。这样的过程反复多次直到每帧画面的 90% 时钟周期都能通过模拟器,确保 profile 具有相当高的可信度。
对于这些模拟测试,Intel 使用以 "Larrabee 单元"为单位来衡量负荷性能。一个 Larrabee 单元就是指一个 1GHz Larrabee 内核,频率的选择完全是因为方便衡量,真正出货的 Larrabee 会有多个内核及不同时钟速度的版本。如果考虑 FMADD 指令为两个浮点操作的话,一个 1GHz Larrabee 内核的浮点性能是 32 GFLOPS。
Larrabee 内核性能延展性分析
Larrabee 的设计是一个 many-core(众核)处理器,它的一个重要应用就是游戏渲染,内核数量与性能的关系即延展性在游戏中的表现如何相当重要。在这个性能模拟中,Intel 采用了六种内核规模配置,并且为每个配置都提供了相应倍数的内存带宽、纹理过滤延伸搭配。

英特尔提供的在不考虑内存带宽限制情况下的内核性能延伸性模拟结果
在延展性分析中,Larrabee 的性能和内核数基本上呈线性延伸,在达到 48 内核规模的时候,线性加速比下降了 7~10%。 Intel 表示如果这个结果是以每 1000 个 Primitive 为一个 Primitive Set 进行 Primitive 分组的。如果 Primitive Set 以 200 Primitive 个为一组的话,F.E.A.R 的线性加速比就会只下降 2%,故此修改代码是能够改善加速比的。

上图为达到 60fps 帧率的性能时所需的“Larrabee 单位”数量估算。在这里,HL2 EP2 需要大约 10 个 LRB 单位,FEAR 和 GOW2 需要大约 25 个 LRB 单位。
除了 Primitive Set 的大小外,影响延展性的另一个因素是软件 lock (锁定)。以如此高细节度的水平来模拟渲染多帧画面的代价是极高的。但是 Larrabee 的这个软件渲染流水线已经是被明确地设计为把 lock 次数以及其他同步事件最小化。通常来说,软件渲染流水线会对下面的事件发生 lock 和 release(释放):
如果将 bin 放入 active list(运作列表),会产生两次 lock/release(一次位于 front-end,一次位于 back-end)。
当 front-end 处理 Primitive Set 或者 back-end 处理 tile 的时候。
一些低频的 lock 例如资源创建及删除、被 host 端 CPU 修改缓存、帧翻转与呈现的时候。
按照 Intel 的说法,大多数游戏的一帧画面 lock 数量通常远远少于 10000 次。对于每个内核每次占用大约 100 个周期的“低竞争锁定”,Larrabee 环形网络可以提供非常出色的同步传输性能。这些数字都非常低,只要内存带宽足够,就足以确保在内核数量线性增加的情况下 lock 的增加不会对性能的延伸构成多大的影响。
Binning 与内存带宽的研究
Larrabee 的软件渲染流水线采用 Binning(分仓)算法的首要目的就是为了让软件 lock 的次数最小化,同时也能令负载平衡和内存带宽可以从中获益。
这个算法会向任何就绪的内核递交 back-end tile,任务分派的时候并不尝试执行负载平衡。理论上这样的做法会导致明显的负载失衡,虽然内核有空可以开始处理下一个 RTset 或者切换到 front-end 处理。然而在 Intel 研究过的游戏负荷中,Bin 负载失衡并非一个问题。

上图是对游戏 Gears of War 16 张单独帧画面在 back-end bin 处理时间上的跟踪记录。每个跟踪记录记下了一帧画面在屏幕上各个 bin 的处理时间,依照从最快的 bin 到最慢 bin 排序,并以处理该帧画面各 bin 的平均时间作为 1.0 进行规格化。
大多数的 bin 处理时间在平均时间的 1/2 到 2 倍范围以内,极少超出平均值的 3 倍,F.E.A.R 和 HL2 EP2 也是类似的结果。
这个模拟器理论上是假设为每个内核提供了无限的内存带宽,但是这样的假设是否会忽略了这个宝贵资源的实际限制呢?对此,Intel 的工程师其实也是有做相应的研究,测定了三个游戏下的内存带宽需求,并且与传统的立即渲染模式算法作了对比。

上图就是 Larrabee 内核采用 binning 模式和立即模式运行三个游戏的时候每帧总带宽需求对比,数据的排列次序依照立即模式从最少带宽需求的帧到带宽需求最高的帧来排列。
Intel 用于测试对比的这个立即模式渲染器被假设成拥有完美的层阶深度剔除、128KB 纹理 cache、1MB 的深度和色彩 cache。
此外,这个立即模式渲染器在每像素 1x 取样的时候拥有两倍的色彩缓存压缩和 4 倍的深度缓存压缩,而在每像素 4x 取样的时候拥有 4 倍色彩缓存压缩以及 8 倍的深度缓存压缩。
从对比结果来看,立即模式处理每帧画面的带宽需求都更高:在 F.E.A.R 中是 2.4~7 倍;在 Gears of War 中,是 1.5~2.6 倍,在 HL2 EP2 中是 1.6~1.8 倍。
当立即模式所需的内存带宽最高时,binning 模式相对地也能达到了最佳的带宽提升效率,这很可能是因为在立即模式由于 overdraw(无效渲染)被迫多次访问内存。
即使结合深度剔除和帧缓存压缩技术,1MB cache 依然不足够捕捉到大多数的 overdraw。随着分辨率的提升,binning 渲染方式的优势就越明显,因为分辨率越高带宽压力就越高。
不同渲染阶段的性能分析

上图提供了三个游戏在 alpha blend(阿尔法混合)、Pixel Shade(像素着色)、Pixel Setup(像素设置)、Depth Test(深度测试)、RasterizATIon(光栅化)、Vertex Shade(顶点着色)、Pre-Vertex(顶点预处理)等渲染阶段的时间占用对比。
普遍而言,pixel shading 和 interpolATIon(插值)是最耗时间的,但是在不同的游戏中,不同渲染阶段均衡性会有很大的变化。例如在 F.E.A.R 中,光栅化和深度运算占的时间就相当多,表明了动态配置运算资源的重要性。

上图是单列出游戏 F.E.A.R 25 帧画面的不同渲染阶段运算时间占用比率。对于其他的两个游戏,各帧画面的不同阶段运算时间比率都是大致相当的,而 F.E.A.R 则有很大的起伏,不仅如此,即使是一帧画面内,F.E.A.R 的变化比率也是相当大的。
Larrabee 的每个内核一次处理一个完整 tile,然后再处理下一个并以此类推,从而在整帧画面的渲染上形成一个合理的非一致负载分布。
相比之下,立即模式渲染器并没有太多的办法来乱序处理像素和 primitive。更进一步而言,大幅度的变动负载会导致立即模式渲染器的不同处理单元在不同时间成为瓶颈,除非这些单元针对最糟糕的情况作了超裕量设计。
#p#副标题#e#
● 高级应用——众核编程模型
Larrabee NATIve(Larrabee 本机)编程模型类似于现在的 x86 多核架构编程模型。 Intel 目前提供了一个编译器,可以把现有不少的 C/C++ 代码程序编译为 Larrabee x86 指令程序,让 Larrabee 可以执行,特别是对高性能运算以及数学密集运算的程序接驳来说,能显著提高开发效率。按照 Intel 08 年的论文,当时这个编译器还存在两个限制,一个是应用程序系统调用移植并未支持以及目前的驱动架构需要应用程序重新编译。
程序编程
Larrabee NATIve 提供了灵活的软件线程执行能力。体系架构级线程执行能力以众所熟知的 POSIX Threads API(P-Threads)提供。 Intel 扩展了该 API,允许开发人员指定线程于特定的硬件线程或者内核。
虽然 P-Threads 是强大的线程编程 API,但是它的线程创建以及线程切换代价对某些应用程序线程执行来说可能太高了。为了分摊这些代价, Larrabee NATIve 提供了一个基于轻量任务分发挪用调度器的 task scheduling(任务调度)API,你可以在 Intel Thread Building Block 中找到这个任务编程 API 的成品实例。最后,Larrabee NATIve 透过在 Larrabee NATIve C/C++ 编译器中的 OpenMP 语法提供了更多的线程编程支持。
对 Larrabee NATIve 应用程序程序员来说,Larrabee 的所有 SIMD 向量单元都具备完全的可编程能力。Larrabee NATIve 的 C/C++ 编译器包含了一个 Intel 向量编译技术的 Larrabee 版本。需要对 Larrabee 的向量单元进行编程的开发人员,可以直接使用 C++ 向量 intrinsics(本生函数,类似汇编的函数,但是使用上灵活一些)或者嵌入 Larrabee 汇编代码来实现。
在基于 CPU 的平台内如果有一片 Larrabee 插卡的话,那么这个 Larrabee 将由为该平台编写的一个操作系统驱动程序所管理。在这样的平台中,Larrabee NATIve 二进制代码是与主机二进制代码紧密捆绑的。
Larrabee 程序库提供快速的信息/数据通信协议来管理两者二进制代码之间所有的内存传输和通信。这个 API 支持同步和异步数据传输。此外,某些被 Larrabee 应用程序二进制代码调用的 C/C++ 标准程序库函数的执行必须和主机操作系统共享。特别是文件 I/O 函数例如 read、write、open、close 等,如果由 Larrabee 应用程序二进制代码委用这些函数至一个服务的,那么这个服务必须在主机操作系统上远程执行。
除了高吞吐的应用程序编程外,Intel 还期盼开发人员会同样采用 Larrabee NATIve 去实现那些可能让并行编程自动化或者专注于某些领域的更高阶编程模型。例如 Intel 前年开始推动的 Ct 风格编程模型、诸如 Intel Math Kernel 的高级程序库 API 以及物理 API。如果有必要的话,现有的 GPGPU 编程模型同样可以透过 Larrabee NATIve 得以复用。
不规则数据结构的支持
Larrabee 对使用了不规则数据结构(例如复杂指针树、空间性数据结构或者大规模稀疏 n 次元矩阵)的高吞吐应用程序提供了优秀的支持。Larrabee 的编程模型、分级存储器体系以及 VPU 指令提供了对这些应用的支持。
对 Larrabee 应用程序而言,多线程化 C++ 代码对这些数据结构的 populate(填入)、transform(变换)或者 traverse(遍历)遵循在多核 CPU 上使用的为人熟知的编程方法。
C++ 指针、inheritance(继承)以及 classe(类)可以用于执行 graph node(关系图节点)。个别的节点可以有显著的操作执行成本或者代码分支行为差别。
由于线程或者任务调度是受程序员控制,对这些数据结构操作的任务能够动态地能被重新捆绑以维持 SIMD 的效率。
例如,一个 ray tracer(光线追踪器)的次要倒影光线可能会采用有别于产生出这些光线的主镜头光线的方式重新捆绑。
最后,诸如预配置内存池的数据结构技术能够应用不对称方式,只对给定的数据结构节点供给所需的内存。
例如,一个顺序无关的半透明(order-independent transparency)实作,Larrabee 可以动态地依照每个像素透明层数来分配内存,而非像 K-buffer 技术那样采用会由于对每像素透明层数估计过高而造成浪费的预先配置。
和基于 stream 方式的计算体系结构(例如 STI 的 Cell 和斯坦福大学的 Imagine)不同的是,Larrabee 无需直接软件管理就能往分级存储器的不同层级装载进数据。软件只不过是把数据读取或者写入到地址中,硬件就能透明地在不同的层级间装载数据。软件的复杂度显著降低,并且数据结构可以采用难以预测的非结构化的内存存取。
在 NVIDIA 新近的 GPU(例如 G8x/G9x/GT200)里,提供了一个被称作 PBSM(Per-block shared memory)的 16KB 大小局部共享内存。
每个 PBSM 由位于一个 SIMD 多处理器中 8 个标量处理器上运行的 768 个(GT200 是 1024 个)程序 instance(实例,NVIDIA 称之为 thread(线程))所共享。
为了实现高速局部共享,程序员必须显式地往 PBSM 装载共享的数据结构。位于不同 SIMD 处理器内核内的 instance 无法对这些数据实现直接共享。同样,次序以及连贯性保护需要软件发射一个只有在同一个 SIMD 处理器内核内才能看到的(barrier sync)栅拦同步信号才能实现。
为了便于在 SIMD 处理器内核之间广泛地共享,数据必须被显示地写出到更高延迟的 GDDR 内存里。
与之相比,在 Larrabee 上的所有内存都是由所有处理器内核所共享的。对 Larrabee 程序员来说,局部数据结构的共享是透过一致性的 cache 化多层次内存结构所支持,无需考虑线程使用的哪个处理器。由传统的软件 lock、semaphore(旗语)、critical section(临界区)等技术提供局部共享数据的保护。
处理不规则数据结构的一个重要要素是要有高效的 scatter/gather(散射/聚集)支持,这样 Larrabee 的 SIMD VPU 才能够在非连续的数据上运作。
如前所述,Larrabee 提供了 VPU scatter/gather 指令,可以从 16 个非连续的内存位置上转载数据至一个 VPU 向量寄存器。非连续的数据元素可以位于 Larrabee 的大型片上 cache 离得任何位置上,这样就能减少内存访问的性能惩罚了。这个支持能显著地减少程序员的数据管理开销。
根据 Intel 自己的研究观察所得,在基本的 稀疏矩阵计算内核例如稀疏矩阵向量乘中,Larrabee 硬件支持 scatter/gather 相对于软件实现 scatter/gather 的方案能获得平均三倍的性能增长。需要不规则数据结构的算法同样能从 Larrabee 的 count bit、bit scan 以及 packed load/store 指令上获益。
扩展的渲染应用范例
Larrabee 图形渲染流水线本身就是 Larrabee NATIve 的实际应用。由于这个渲染器是使用语言和工具编写的软件,它可以轻易地扩展,引入创新性的渲染能力。在 Intel 的论文中,提供了三个这样的例子。
——Render Target Read(读取渲染目标)
由于 Larrabee 的图形渲染流水线采用了软件帧缓存,可以让更多的程序员存取这些数据结构。更明确一点来说,对 Larrabee 渲染流水线的一个普通扩展将允许 Pixel Shader(像素着色器)直接读取之前存放在 Render Target 内的数值。 这个能力可以为多种渲染应用所使用,包括程序员定制化的混合操作、single-pass 的 tone mapping 以及相关功能。
——Order Independent Transparency(次序无关半透明)

左图:先画小飞龙,因此它的翅膀在大飞龙的后面了
右图:渲染的像素经过排序后,大飞龙的翅膀显示正确了
在目前,3D 应用程序开发人员必须在程序每帧渲染之前对透明模型进行深度排序或者执行诸如深度剥离的 multi-pass(多次)算法,以达成模型间正确的透明度。
不管哪种办法,都不能像非透明模型那样实现正确的局部的 post-processing(后处理)效果。

左图:透明翅膀无法展现翅膀另一侧的雾化效果
左图:透明翅膀可以展现翅膀另一侧的雾化效果
Larrabee 可以在没有额外专用电路的情况下,透过一个每像素空间数据结构对多个透明表面的排序实现对 order independent transparency (OIT,次序无关透明)的支持。
——Irregular Shadow Mapping(不规则阴影映射)
Shadow mapping(阴影映射)是一个流行的实时阴影近似技术,但是大多数的 shadow mapping 实现方式都存在让人恼火的锯齿瑕疵。Irregular Shadow Mapping 是针对此问题的一个精确解决办法,而且不会让编程人员有额外负担。
为了执行 ISM,Larrabee 动态地在光照视点里使用由观察视点捕获的深度样本构建一个空间数据结构。然后透过针对 ISM 空间数据结构,增加一个执行光照视点 ISM 光栅化的渲染工位,定制 Larrabee 的所有软件图形流水线。

Intel 提供的 ISM 应用于柔和阴影的效果示范图
由于 shadow map 是在精确的位置计算而得,得出的 shadow map 是没有锯齿的。该技术能被用于实时硬边缘阴影效果以及实时边缘柔和阴影效果。
其他类型的高吞吐运算应用范例
Larrabee 还适合于大量的非光栅化高吞吐应用。以下就是在 Larrabee 论文中提供的若干举例。
——游戏物理

上图是 Intel 在不同 Larrabee 内核规模配置上执行多种游戏物理负载的延展性模拟结果图,测试的物理负荷包括了刚体、液体以及布料等。
在这个测试中,Intel 在 64 个 Larrabee 内核的配置上获得了超过 50% 的利用率,在其中的某些场景中达到了近乎线性的延伸率。
刚体模拟是 castle(城堡)被摧毁的场景,有大约 10000 个对象。
Sweep-and-Prune(卷走并剪除)以及GJK(Gilbert–Johnson–Keerthi 算法)距离算法也包含于对比,是因为这两个算法属于在碰撞侦测程序中最常用的两个算法。
游戏液体模拟是基于 smoothed particle hydrodynamics (SPH,平滑化粒子流体力学)算法。
对于游戏布料模拟,Intel 采用了一个质量弹簧模型以及 Verlet 积分算法。
——Ray Tracing(光线追踪)

Whitted 氏式的实时 ray tracer(光线追踪器)所使用的空间数据结构存在高度的不规则性,能受益于 Larrabee 的通用多级存储器体系、较短的流水线以及 VPU 指令集。
Intel 在论文中提到了使用 SIMD 16 分组在一个 KD-Tree(KD-树)中传导的 ray tracing 。要完成整个工作量,Intel 观测到单个 Core 2 Duo 处理器需要单个 Larrabee 内核的 4.67 倍时钟周期,这显示出了 Larrabee 指令集及其宽幅 SIMD 的有效性。
对于小型的运算内核,测试结果甚至更高。例如,在一个三角形上的 16 个交集测试,单个 Larrabee 内核只需要花 47 个周期就能完成。
同样的运算在 Core 2 Duo 处理器上需要花掉 257 个周期。上图是一个 1024x1024 大小的酒吧场景,里面有 234000 个三角形、一个光源、一个倒影层,每帧画面大约有 4 百万条光线。

上图是 Larrabee 和拥有 8 个内核 的 2.6GHz Xeon 处理器执行一个光线追踪器实例的对比。
——图像及视频处理
Larrabee 架构非常适合于许多传统 2D 图像及视频分析应用。传统 2D 滤镜功能(包括线性和非线性)的直接实现以及更先进的功能(例如 视频镜头索引、体育运动视频分析、人体跟踪、前景预测等应用表现出了可观的延展性。生物医学图像就是这类处理类型的一个重要分支。医学图像需要诸如背投影、立体渲染、自动分割以及健全的变形配准,这些特性相对消费类图像图形来说并没有多大的区别。

上图的结果中包括了使用行进立方体算法对一个 3D 实体数据组进行等积表面抽取运算的延展性分析。
——物理模拟
物理模拟应用程序采用数值模拟在电影和游戏中模仿复杂的自然现象,例如虚拟世界中的火焰效果、瀑布;刚体或者可变形体对象之间的碰撞。
大规模的数据组、非结构化的 control flow(控制流)和数据存取通常让这些应用程序较传统的流式应用程序更难在性能上获得良好的延展性。
除了关注交互式的游戏物理计算,Intel 还分析了 Larrabee 在包括离线电影工业特效、分布式实时虚拟世界模拟等娱乐产业物理的适用性。在上一小节的图片中提供了基于斯坦福大学 PhysBAM 为基础的特定模拟结果,表明 Larrabee 在成品级液体、布料、面部模拟上具备良好的性能延展性。
#p#副标题#e#
● 与 Cell BE、Tesla 的对比
在这一节中,我不打算把 Cell BE、Tesla 的细节如前面介绍 Larrabee 那样再全面铺出,进行扼要简单的介绍应该已经基本足够了。
| 架构名称 | Larrabee | Cell BE eDP | Tesla 10 |
| 芯片名称 | Larrabee | PowerXCell 8i | T10P |
| 芯片厂商 | Intel | IBM(STI Center) | NVIDIA |
| 产品名称 | Larrabee Extreme(?) | GigaAccel 180 | Tesla C1060 |
| 产品类型 | 加速卡 | 加速卡 | 加速卡 |
| 产品上市时间 | 2010 年上半年 | 2009 年 2 月 24 日 | 2008 年 11 月 19 日 |
| 制造工艺 | Intel 45nm | IBM 65nm | TSMC 55nm |
| 芯片面积 | ~650mm^2 | 212 mm^2 | 460 mm^2 |
| 系统架构类别 | 相同ISA异质架构 | 不同ISA异质架构 | 不同ISA异质架构 |
| 内核数量 | 32 | 1+8 | 30 |
| 频率 | ~2GHz | 2.8GHz | 1.3GHz |
| 单精度性能 | 2048 GFLOPS[fmad] | 179.2 GFLOPS[fmad] | 933 GFLOPS[fma+mul] |
| 双精度性能 | 1024 GFLOPS[fmad] | 89.6 GFLOPS[fmad] | 78 GFLOPS[fma] |
| 专用内存容量 | 未知 | 4GB | 4GB |
| 内存速度 | 未知 | DDR2-800 | GDDR3-1600 |
| 内存界面 | 未知 | 256-bit | 512-bit |
| 内存带宽 | 未知 | 25.6GB/s | 102.4GB/s |
| 软件开发套件 | Larrabee NATIve SDK | Cell BE SDK | CUDA SDK |
Larrabee 目前还只是处于原型阶段,虽然已经有了芯片实物,但是具体的频率等规格还只能是依照不确定的消息给出,而内存规格则基本上是空白。
与当前的其他两款产品相比,Larrabee 和 Cell、GT200 其实都属于异质架构,LRBni 在与 x86 存在一定的差别,例如寄存器数量、指令编码等,但是由于 VPU 与标量单元紧密耦合,而 Larrabee 标量单元本身是 x86-64,所以我们将其称作相同 ISA 的异质架构,或者这至少是 Intel 正在努力的方向。按照 Intel 的说法,未来 LRBni 还是会融合到传统意义上的桌面处理器中,当然什么时候以及什么形式就是一个大问题了^^。
Larrabee、Cell BE、Tesla 都有一定的共通点:高吞吐的运算能力、高内存带宽、透过软件管理的小型片上内存来提高运算效率。

CELL BE DD2 处理器的功能模块图

65nm 的 Cell BE eDP(PowerXCell 8i)

采用 PowerXCell 8i 的 QS22 刀片服务器

采用 PowerXCell 8i 的 GigaAccel 180 加速卡

采用 PowerXCell 8i 的 GigaAccel 180 加速卡
而在具体的执行上,Cell BE 作为三者中的前辈(2001 年开始构思,2005 年推出 DD2 版,2008 年 推出双精度增强版),由于受到当时各种条件的制约,存在着不少约束。
特别是 SPU 的内存定址空间只有和 Local Storage 一样大小的 256KB,几乎不存在多层次内存架构,让不少人程序员绞尽脑汁,例如透过 double buffer 的方式来实现高效程序/数据搬迁。当然,这个设计是有弊也有利的,最重要的是简化了 Local Storage 的电路设计,这通常意味着芯片耗电、成本的降低。
不过对 PC 市场来说来说,Cell BE 最大的问题在于它定位上纯粹只是作为运算加速卡,很难被 PC 市场广大用户所接受。
缺乏足够的装机量与关键应用程序的匮乏,使得 Cell BE 在 PC 市场上面临着无法跨越的鸡和蛋的问题,因此系统集成是 Cell BE 在 PC 上的主要销售途径。


GT200 65nm 裸片图

基于 55nm GT200b 的 Tesla C1070 1U 服务器

基于 55nm GT200b 的 Tesla C1060 加速卡
PC 市场每年的出货量差不多有两亿台,NVIDIA 占有其中大约 25% 的份额,这就是相当于 5000 万台的装机量,加上差不多每 18 个月的制程升级,这意味着今天的高端 GPU 在明天可能就会成为中端甚至低端的 GPU,高性能不仅随手可及而且价格便宜。NVIDIA 已经花费了两年多的时间大力推动 CUDA 软件开发包以及开办了大量的研习班,使得程序员乐于为这样的产品开发应用,而即将问世 OpenCL 和 Compute Shader 更是让 GPU 运算应用普及如虎添翼。
Tesla 采用了虚拟式的 ISA(指令系统架构)——PTX,实际的本机 ISA (Tesla ISA?)只有 NVIDIA 自己知道,并不公开,不过在 open64.org 上倒是有一个叫 NVISA 的东西,里面有大量 PTX 文档没有提及的指令,现在也有一个名为 Barra 的模拟器,可以使用 GPU 的本机指令执行 CUDA SDK 50 个例程中的 19 个。
这其中的原因主要是 GPU 的发展速度相当快,而 GPU 本身目前又包含了大量的功能固化单元,如果 ISA 每两年就出现大的变化,对开发工具的开发人员来说,将是非常麻烦的事情。不过随着半导体工艺的进步,统一着色器的运算比例显著增大,NVIDIA 在 ISA 的上正式确立相信是数年内就能看到的事情了,不过虚拟 ISA 还是首选,因为这可以实现 CPU/GPU 代码的统一。
| 架构名称 | Larrabee | Cell BE eDP | Tesla 10 |
| ISA | x86 + LRBni | PPC + SPU ISA 1.2 | PTX(虚拟 ISA) |
| 流水线执行 | In-Order | In-Order | In-Order |
| control task | host/scalar unit | PPE | host(CPU) |
| data-intensive process | VPU | SPE | device(GPU) |
|
|
|||
| SIMD 宽度[单精度] | 16D/cycle | 4D/cycle | 32D/4 cycle |
| work-item 术语 | strand | N/A | thread |
| work-group(WG) 术语 | 未定义 | N/A | CTA |
| 线程动态调度 | SMT-based | N/A | warp-based |
| In-Flight HW thread | =<4 SMT Thread | SPE:1 Thread PPE:2 Thread |
=<32 warp |
| VU memory hierarchy | register | L1/L2 Cache | device memory | host memory |
register | Local Storage | DMA-main memory |
register | shader memory | device memory | host memory |
| register file | 4*32*512-bit | 128*32-bit | 16384*32-bit 4~128 per SP |
| scratch-pad memory | =L2(L1-D) cache 1 Cache Line/cycle |
256 KB 1 Cache Line/cycle |
16 KB 16 Bank/cycle |
| L1 cache | 32 KB + 32 KB | PPE: 32 KB + 32 KB SPE: N/A |
N/A |
| L2 cache | 256 KB | PPE: 512 KB SPE: N/A |
N/A |
| fma 指令时延[clock] | 4~9 | 7 | 24 |
|
|
|||
| interconnects | Ringbus 16 core: 512-bit*2 n 16 core: X-Ring |
Ringbus 128-bit*(4+2) |
Crossbar |
| host/device interface | PCIE + QPI | FlexIO | PCIE |
Intel 、NVIDIA 乃至 AMD 在一些术语都有自己的一套,例如 thread、strand、fiber、warp、wavefront 等等,NVIDIA 里的 thread 似乎太小,而 Intel 的 fiber 也似乎大了一些,因此我们在上面这个表格中尝试使用 OpenCL 的 work-item、work-group 来统一这类名词,不过这也只能是做到近似,例如 Larrabee 就还没有 work-group 方面的细节。
在 Memory Hierarchy 方面,实际的情况要比上表复杂一些,例如 CUDA 还有 texture cache、constant cache、instruction cache 这三个片上 cache 以及 local memory、golbal memory、constant memory、texture memory 这四个同属于 device memory 的细节性定义。

NVIDIA 的 shared memory 虽然不是 cache,但是在一些特性上要比 cache 好,例如它有 16 个 bank,还能实现 broadcast,只是尺寸小了点。
此外,我们如果稍微了解 CUDA 的话,就可以知道 CUDA 里有 thread、warp、thread block(又被称作 CTA)这样的线程单位,其中 warp 其实是一个微架构上的东西,在编写程序的时候,程序员会写代码定义 thread block 和 thread 的大小,但是不会定义 warp。
Warp 是 thread block 被发送到内核(即 SM)的时候才会被切出来,SM 内的调度器以 warp 为单位把线程发射到 SIMD 运算器上执行,warp 的大小限制依照微架构的不同而不同。
在 G8x/G9x 上 Warp 最多是 32 个 thread,每个 thread block 最多可以切出 24 个 warp,而在 GT200 或者说 T10P 上 warp 的都是一样最大为 32 thread,但是一个 thread block 可以切出最多 32 个 warp。
CUDA 的 warp 可以实现动态调度,例如一个 thread block 里有 256 个 thread,如果已经有 128 个 thread 跑完了,那么 SM 的 warp 调度器就不会再去跑这些 thread 了,算是一种简单的 out-of-order 执行。
在 Larrabee 上,有一个线程单位类似于 warp,就是我们前面提到的 fiber,一个 SMT 里可以有多个 fiber(具体最高能有多少个 Intel 没有细说,只是说典型为 2~10 个,估计也是微架构相依的)。
但是这个 fiber 的调度是软件管理的,执行顺序是由编译器依照内存存取动作来确定,fiber 在 Larrabee 内核上依顺序(in-order)发射执行,无法动态调度。当然,由于 Larrabee 有 4 个 SMT,所以还是可以做到一个 SMT 里的 fiber 执行出现等待的时候,可以马上切换到另一个 SMT 的 fiber。严格来说,fiber 和 warp 是两回事情。
Larrabee 能实现多任务处理,这是目前的 GPU 无法实现的特性,例如在 CUDA 里,GPU 必须跑完一个 kernel(相当于一个 task)后,待 CPU 那端完成一段串行代码后再执行另一个 kernel,而在 Larrabee 上则完全没有这个限制。
Intel 希望透过执行 x86 ISA 让软件开发人员能尽快熟习 Larrabee,不过这个策略在 many-core 时代恐怕不会有什么立竿见影的效果,因为在现实中已经没有多少开发人员会埋头于汇编的编写,问题也就交给了 Larrabee NATIve 编译器的开发以及第三方应用程序员的身上,难度要比在 NVIDIA CUDA 上开发程序好一些,但是这并非因为 x86,而是因为 Larrabee 的微体系架构更加友好。

Intel IDF 官方网站提供的 Larrabee 晶圆照片

PCGH 网站提供的 Larrabee 裸片图
Larrabee 被设计成可以有多个核心、频率版本,在北京 IDF 2009 春季会议上以及后来在德国曾经展示过它的开发用原型晶圆和裸片。有人根据这些图片估计这个展示的 Larrabee 是 32 内核的( Intel 表示展示的是 Extreme 版本),裸片的面积达到了 600~650 平方毫米。
按照 Realworldtech 的报道,NVIDIA 曾经试图在 GT200 上实现更多的 SM,但是由于受制于 TSMC 65nm 工艺光学遮罩的极限,最终只好做成 30 个 SM。而 Intel 在 45 纳米工艺上实现了 600mm^2 的芯片面积,相信也是接近 Intel 自家 45nm 制造工艺或者 PCIE 供电方面的极限。
Intel 有一个芯片面积更大的产品——65nm 的 Tukwila,芯片面积几乎达到 699mm^2(ISSCC 2008),但是这款原定 2007 年的产品已经被多次推迟,最新的消息是到 2010 年了。
Larrabee 相比之下复杂度一点都不比 Tukwila 简单,因为 Tukwila 其实大部分都是基于 SRAM 的 Cache,而 Larrabee 的运算电路更多,加上 Larrabee 已经把高性能运算作为重要的设计目标,相信也有部分简单的纠错、冗余设计。
和制造工艺相比,最大的障碍恐怕是驱动程序上的问题。 Intel 在 i740 时代的驱动表现其实不错,不过随着 Intel 将图形芯片整合到芯片组后,驱动表现逐渐被 NVIDIA、AMD 抛离,现在同等级的整合芯片组,NVIDIA、AMD 的图形性能都能轻松把 Intel 的产品打得落花流水,驱动程序在其中起重要的作用。
Intel 表示 Larrabee 的驱动团队不同于整合图形芯片组的队伍,其中的主力来自 3D Labs。从好的方面来说,这当然给大家一个新的期盼,但是另一方面,我们必须也注意到,3D Labs 的驱动其实可以说是臭名昭著的。
3D Labs 在收购了 Intense3D 后推出过多款规格上看上去非常漂亮的产品,但是由于缺乏高品质驱动的原因,他们无法将这些产品(例如 P10)如愿地推向游戏卡市场,在无法赢得大市场支撑的情况下,研发费用无法获得合理摊分,最终不得不在 06 年退出显卡市场。
如果没有好的驱动特别是游戏卡驱动,Larrabee 这类产品就会变成非常狭窄的产品,这实际上意味着失败,Intel 在这点上不容马虎。
#p#副标题#e#
● 决战不仅在2010
Larrabee 的推出是大势所趋,在它问世之前,英特尔已经推出过多款显示芯片,最早期的包括本文中提到的 i860 以及在此之后的 i740 和各种整合图形芯片组。虽然 Intel 强调 Larrabee 是基于 x86,但事实上 LRBni 和 x86 的差别相当大,只是这个套指令集在设计的时候就被设计为依赖于现有 x86 上而已。不过在英特尔公布 LRBni 的微代码编码方式之前,这个问题还真的不好弄清楚。
按照 heise.de 的报道,英特尔的副总裁 Joseph D. Schutz 表示 Larrabee 会在 2010 年上半年推出,拥有低端到高端的完整产品线,但是具体的时间暂时不能确定,原因是这中间需要进行步进修改以及除错等步骤,相比之下开发人员能在早得多的时候获得原型版的 Larrabee。
如果不出所料,Larrabee 问世的时候,NVIDIA 和 AMD 都已经有了基于 40nm的 DirectX 11 产品线,Larrabee 首先需要在这个对决中站稳脚跟,而后才能讨论并行计算的问题(因为没多少人只是为了一块运算加速卡而购买产品,Intel 在Larrabee 上的研发经费需要一个大容量的市场来分摊,这个市场就是游戏卡市场),否则 Larrabee 的下场不会比 i860 好多少。

基于 x86-ISA 的另一个 many-core 架构:POD
英特尔在着手进行 Larrabee 的同时,还有许多 many-core 的项目在进行,其中一个比较有趣的项目叫 PARALLEL-ON-DEMAND,简称 POD。在目前看到的资料中,POD 是一个基于三维堆叠的芯片架构,主要的目的是为了解决芯片内部互连的成本、性能问题,这是因为随着内核规模的增长,内存带宽问题将会日显突出。在很大程度上而言,POD 比 Larrabee 更胜任 many-core 世代。

NVIDIA 的新任首席科学家 Bill Dally 在“Computer Architecture Research in the 2010s”的演讲中也有一些类似的看法,上图所示的就是他提供的一份关于在 16 毫米见方的芯片中 64-bit 浮点和 16-bit 定点计算在运算单元和内部互连、外部链接上的能源消耗对比。内核的增加,带来的传输成本增加困扰着所有参与其中的厂商。
回顾当年 x86 和 RISC 阵营的对决,英特尔由于有先进工艺和可以吸收研发先进工艺所需资金的庞大市场空间,得以最终胜出,这中间凭借的就是往 x86 处理器添加各类 post-RISC 技术。
而在 Larrabee 开启的 many-core 世代里,英特尔很可能会在后续的产品中把三维堆叠等先进的芯片制造作为重要的利器,用 x86 vs RISC 类似的手法融化掉对手。
备注:
参考:
1、Larrabee: A Many-Core x86 Architecture for Visual Computing:http://www.intel.com/technology/visual/microarch.htm
2、NVIDIA's GT200: InsIDE a Parallel Processor:http://www.realworldtech.com/page.cfm?ArticleID=RWT090808195242
3、Intelヒルズボロが開発するCPUアーキテクチャの方向性:http://pc.watch.impress.co.jp/docs/2008/1217/kaigai481.htm
4、NVIDIA Tesla: A Unified Graphics and Computing Architecture:http://www2.computer.org/portal/web/csdl/doi/10.1109/MM.2008.31
5、Next-GenerATIon Graphics on Larrabee:http://sa08.idav.ucdavis.edu/foley-nextgen.pdf
6、Efficient Throughput Cores for Asymmetric Manycore Processors:http://www.cs.virginia.edu/~skadron/Papers/tarjan_phd.pdf
7、Barra, a Modular Functional GPU Simulator for GPGPU:http://hal.archives-ouvertes.fr/docs/00/37/47/15/PDF/stats_on_instruction.pdf
8、The OpenCL SpecificATIon 1.0:http://www.khronos.org/registry/cl/specs/opencl-1.0.43.pdf